package com.dctimer;

import static com.dctimer.Configs.*;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.*;

import com.dctimer.adapter.ListAdapter;
import com.dctimer.adapter.TextAdapter;
import com.dctimer.db.*;
import com.dctimer.model.Stackmat;
import com.dctimer.model.Timer;
import com.dctimer.ui.CustomDialog;
import com.dctimer.util.*;
import com.dctimer.view.ColorPickerView;
import com.dctimer.view.ColorSchemeView;
import static com.dctimer.Configs.DB_TBL_COUNT;

import scrambler.Scrambler;
import solver.Sq1Shape;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.app.Service;
import android.content.*;
import android.content.DialogInterface.OnClickListener;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
import android.graphics.*;
import android.graphics.Bitmap.Config;
import android.graphics.drawable.Drawable;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.net.Uri;
import android.os.*;
import android.os.Build.VERSION;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.*;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.*;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TabHost.TabSpec;

@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public class DCTimer extends Activity implements OnTouchListener{
	private GestureDetector mGestureDetector;
	private static PermissionListener mListener;
	private static String[] PERMISSIONS_STORAGE = {
			"android.permission.READ_EXTERNAL_STORAGE",
			"android.permission.WRITE_EXTERNAL_STORAGE",
			"android.permission.RECORD_AUDIO"};

	public Context context;
	private TabHost tabHost;
	private RadioButton[] rbTab = new RadioButton[4];
	private RadioGroup rGroup;
	private WebView webView;
	
	private Button btScramble;	//打乱按钮
	private PopupWindow popupWindow;	//打乱弹出窗口
	private TextAdapter scr1Adapter;
	private TextAdapter scr2Adapter;
	private TextView tvTimer;	//计时器
    private TextView tvAvg;	//平均统计
	private TextView tvScramble;	// 显示打乱
	private Bitmap bmScrView;
	private ImageView scrambleView;	//打乱状态图
	
	private ListView lvTimes;	//成绩列表
	public ListAdapter timeAdapter;
	private LinearLayout layoutTitle;	//成绩标题
	private Button btSesMean, btSesOptn, btSession;	//分组平均, 分组选项, 分组
	private Button btOutSetting, btInSetting;
	private Button btOption;
	private TextView tvSesName, tvTxtSesName;	//分组名称
	
	private TextView tvTitle;	//设置
	private TextView[] tvSettings = new TextView[6];
	private TextView[] std = new TextView[24];
	private TextView[] stdn = new TextView[9];
	private SeekBar[] seekBar = new SeekBar[8];	//拖动条
	private ImageButton[] ibSwitch = new ImageButton[11];	//开关
	private Button[] btSolver3 = new Button[2];	//三阶求解
	private RelativeLayout[] llayout = new RelativeLayout[43];
	private CheckBox[] checkBox = new CheckBox[11];	//EG打乱设置
	private Button btReset;	//设置复位
	private Button btResetColor;	//颜色复位
	private Button btAbout;	//关于

	private TextView tvPathName;
	private View tabLine;
	private Boolean showTabLine;
	private View view;
	private ListView listView;
	private ProgressDialog progressDialog;
	private EditText editText;
	public Bitmap bitmap;
	
	public SharedPreferences share;
	public static SharedPreferences.Editor edit;
	public static DisplayMetrics dm;
	
	public Scrambler scrambler;
	public Timer timer;
	public Session session;
	public Stackmat stm;
	public Vibrator vibrator;
	private SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault());
	
	private boolean nextScrWaiting = false;
	private boolean scrTouch = false;
	private boolean isLongPress;
	private boolean touchDown;
	public static boolean canStart;
	private int mulpCount;
	private int version;
	private int[] resId = {R.drawable.img1, R.drawable.img2, R.drawable.img3, R.drawable.img3, R.drawable.img1_selected, R.drawable.img2_selected, R.drawable.img3_selected, R.drawable.img3_selected};
	private int selScr1, selScr2;
	private int crntProgress;
	private long exitTime = 0;
	private String newVersion, updateCont;
	public static String dataPath;
	private static String slist;
	public List<String> items = null, paths = null;

	private SoundPool soundPool;
    public int promptSec = 0;

    private int matchIdx = -1;

    private int[] delSesId = null;

	interface PermissionListener {
		void granted();
		void denied(List<String> deniedList);
	}

	@SuppressLint("HandlerLeak")
	private Handler handler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			int msw = msg.what;
			switch (msw) {
			case 0: tvScramble.setText(scrambler.crntScr); break;
			case 1: tvScramble.setText(scrambler.crntScr + "\n\n" + getString(R.string.shape) + extsol);	break;
			case 2: tvScramble.setText(getString(R.string.scrambling));	break;
			case 3: tvScramble.setText(scrambler.crntScr + extsol);	break;
			case 4: tvScramble.setText(scrambler.crntScr + "\n\n" + getString(R.string.solving));	break;
			case 5: Toast.makeText(context, getString(R.string.save_failed), Toast.LENGTH_SHORT).show();	break;
			case 6: Toast.makeText(context, getString(R.string.file_error), Toast.LENGTH_LONG).show();
			case 7: Toast.makeText(context, getString(R.string.save_success), Toast.LENGTH_SHORT).show();	break;
			case 8: Toast.makeText(context, getString(R.string.conning), Toast.LENGTH_SHORT).show();	break;
			case 9: Toast.makeText(context, getString(R.string.net_error), Toast.LENGTH_LONG).show();	break;
			case 10: Toast.makeText(context, getString(R.string.lastest), Toast.LENGTH_LONG).show();	break;
			case 11: Toast.makeText(context, getString(R.string.import_failed), Toast.LENGTH_SHORT).show(); break;
			//case 12: Toast.makeText(context, getString(R.string.import_success), Toast.LENGTH_SHORT).show(); break;
			case 12: Toast.makeText(context, getString(R.string.import_success), Toast.LENGTH_SHORT).show();
				forceReboot();
				break;
			case 13:
				btSesMean.setText(getString(R.string.session_average) + Statistics.sessionMean());
				setListView();
				break;
			case 14: scrambleView.setVisibility(View.GONE); break;
			case 15:
				scrambleView.setVisibility(View.VISIBLE);
				scrambleView.setImageBitmap(bmScrView);
				break;
			case 16:
				if(defPath == null)
					Toast.makeText(context, getString(R.string.sd_not_exist), Toast.LENGTH_SHORT).show();
				else
					new CustomDialog.Builder(context).setTitle(getString(R.string.havenew)+newVersion).setMessage(updateCont)
					.setPositiveButton(R.string.btn_download, new OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							download("DCTimer-"+newVersion+".apk");
						}
					}).setNegativeButton(R.string.btn_cancel, null).show();
				break;
			case 17:
				timeAdapter.notifyDataSetChanged();
				if ( -1 != matchIdx ) {
					lvTimes.setSelection(matchIdx);
				}
				matchIdx = -1;
				setTimerAvg();
                break;
			case 18: tvScramble.setText(getString(R.string.initing) + " (0%) ..."); break;
			case 19: tvScramble.setText(getString(R.string.initing) + " (19%) ..."); break;
			case 20: tvScramble.setText(getString(R.string.initing) + " (26%) ..."); break;
			case 21: tvScramble.setText(getString(R.string.initing) + " (34%) ..."); break;
			case 22: tvScramble.setText(getString(R.string.initing) + " (" + (36 + cs.threephase.Util.c4prog / 44809) + "%) ..."); break;
			case 30: timeAdapter.setData();	break;
			case 31: timeAdapter.setHeight((int) Math.round(rowSpacing * scale));	break;
			case 32: lvTimes.setSelection(timeAdapter.getCount()-1); break;
			case 33:
				new CustomDialog.Builder(context).setTitle(getString(R.string.lastest)+" "+getString(R.string.app_version)).setMessage(updateCont)
						.setNegativeButton(R.string.btn_cancel, null).show();
				break;
			default:
				progressDialog.setProgress(msw - 100);	break;
			}
		}
	};

	public void forceReboot()
	{
		new CustomDialog.Builder(context).setTitle(R.string.reboot).setPositiveButton(R.string.reboot, new OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				if(session != null)
					session.closeDB();
				edit.putInt("sel", scrIdx);
				edit.putInt("sel2", scr2idx);
				edit.commit();
				//android.os.Process.killProcess(android.os.Process.myPid());
				Intent intent = new Intent(DCTimer.this, DCTimer.class);
				intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
				startActivity(intent);
				//final Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName());
				//intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
				//startActivity(intent);
			}
		}).show();
	}

	public void changeAppLanguage(Locale locale) {
		Configuration configuration = getResources().getConfiguration();
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
			configuration.setLocale(locale);
		} else {
			configuration.locale = locale;
		}
		getResources().updateConfiguration(configuration, dm);
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		context = this;
		share = super.getSharedPreferences("dctimer", Activity.MODE_PRIVATE);
		edit = share.edit();
		dm = getResources().getDisplayMetrics();

		readConf();
		switch ( Language )
		{
			case 1:
				changeAppLanguage(Locale.SIMPLIFIED_CHINESE);
				break;

			case 2:
				changeAppLanguage(Locale.US);
				break;

			case 3:
				changeAppLanguage(Locale.TRADITIONAL_CHINESE);
				break;

			default:
				changeAppLanguage(Locale.getDefault());
				break;
		}

		requestWindowFeature(Window.FEATURE_NO_TITLE);

		if(VERSION.SDK_INT >= 19) {
			getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
			getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
		}
		if (Build.VERSION.SDK_INT >= 23) {//判断当前系统是不是Android6.0
			requestRuntimePermissions(PERMISSIONS_STORAGE, new PermissionListener() {
				@Override
				public void granted() {
					//权限申请通过
				}
				@Override
				public void denied(List<String> deniedList) {
					//权限申请未通过
					for (String denied : deniedList) {
						Toast.makeText(context, "没有文件读写权限,请检查是否打开！", Toast.LENGTH_SHORT).show();
					}
				}
			});
		}

		super.setContentView(R.layout.tab);
		mGestureDetector = new GestureDetector(new gestureListener()); //使用派生自OnGestureListener

		scale = dm.density;
		fontScale = dm.scaledDensity;
		//System.out.println(scale+", "+fontScale);
		dip300 = (int) Math.round(scale * 300);
		getWindowManager().getDefaultDisplay().getMetrics(dm);
		if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
			defPath = Environment.getExternalStorageDirectory().getPath()+"/DCTimer/";
			//System.out.println("SD卡 "+defPath);
		}
		dataPath = getFilesDir().getParent() + "/databases/";
		//System.out.println("data path: "+dataPath);

		scrAry = getResources().getStringArray(R.array.cubeStr);
		scrAryShow = getResources().getStringArray(R.array.cubeStrShow);
		sol31 = getResources().getStringArray(R.array.faceStr);
		sol32 = getResources().getStringArray(R.array.sideStr);
		for(int i=0; i<itemStr.length; i++)
			itemStr[i] = getResources().getStringArray(staid[i]);
		scr2Ary = getResources().getStringArray(Utils.get2ndScr(scrIdx));
		if(scr2idx >= scr2Ary.length || scr2idx < 0) scr2idx = 0;
		Utils.setEgOll();
		if(fullScreen) getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
		if(opnl) acquireWakeLock();

		scrambler = new Scrambler(this);
		timer = new Timer(this);
		session = new Session(this);
		stm = new Stackmat(this);

		webView = (WebView)findViewById(R.id.web_if);
		WebSettings webSettings = webView.getSettings();
		webSettings.setJavaScriptEnabled(true);
		webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
		webSettings.setAppCacheEnabled(true);
		webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
		webSettings.setDomStorageEnabled(true);
		webView.setWebViewClient(new WebViewClient() {
			//覆盖shouldOverrideUrlLoading 方法
			@Override
			public boolean shouldOverrideUrlLoading(WebView view, String url) {
				view.loadUrl(url);
				return true;
				}
		});
		// 由于设置了弹窗检验调用结果,所以需要支持js对话框
		// webview只是载体，内容的渲染需要使用webviewChromClient类去实现
		// 通过设置WebChromeClient对象处理JavaScript的对话框
		//设置响应js 的Alert()函数
		webView.setWebChromeClient(new WebChromeClient() {
			@Override
			public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
				AlertDialog.Builder b = new AlertDialog.Builder(DCTimer.this);
				b.setTitle("Alert");
				b.setMessage(message);
				b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						result.confirm();
					}
				});
				b.setCancelable(false);
				b.create().show();
				return true;
			}
		});

		tabHost = (TabHost) findViewById(R.id.tabhost);
		tabHost.setup();
		int[] ids = {R.id.tab_timer, R.id.tab_list, R.id.tab_setting, R.id.tab_if};
		int[] rbIds = {R.id.radio_1, R.id.radio_2, R.id.radio_3, R.id.radio_4};
		for (int x=0; x<4; x++) {
			TabSpec myTab = tabHost.newTabSpec("tab" + x);
			myTab.setIndicator("tab");
			myTab.setContent(ids[x]);
			tabHost.addTab(myTab);
			rbTab[x] = (RadioButton) findViewById(rbIds[x]);
			rbTab[x].setOnCheckedChangeListener(mOnTabChangeListener);
			if(x == 0) {
				rbTab[x].setTextColor(0xff3d9ee8);
				Drawable dr = getResources().getDrawable(resId[x + 4]);
				rbTab[x].setCompoundDrawablesWithIntrinsicBounds(null, dr, null, null);
			} else {
				rbTab[x].setTextColor(0xff747474);
				Drawable dr = getResources().getDrawable(resId[x]);
				rbTab[x].setCompoundDrawablesWithIntrinsicBounds(null, dr, null, null);
			}
		}
		rbTab[3].setVisibility(View.GONE);
		tabHost.setCurrentTab(0);
		rGroup = (RadioGroup) findViewById(R.id.main_radio);
		tabLine = (View) findViewById(R.id.tab_line);
		showTabLine = true;
		if(useBgcolor) changeBackgroudColor(colors[0]);
		else try {
			Bitmap bm = Utils.getBitmap(picPath);
			bitmap = Utils.getBackgroundBitmap(bm);
			tabHost.setBackgroundDrawable(Utils.getBackgroundDrawable(context, bitmap, opacity));
			bm.recycle();
		} catch (Exception e) {
			changeBackgroudColor(colors[0]);
			Toast.makeText(context, "Error: "+e.getMessage(), Toast.LENGTH_SHORT).show();
		} catch (OutOfMemoryError e) {
			changeBackgroudColor(colors[0]);
			Toast.makeText(context, "Error: "+e.getMessage(), Toast.LENGTH_SHORT).show();
		}
		//计时
		btScramble = (Button) findViewById(R.id.bt_scr);	//打乱按钮
		btScramble.setOnClickListener(mOnClickListener);
		tvScramble = (TextView) findViewById(R.id.tv_scr);	//打乱显示
		tvScramble.setOnTouchListener(mOnTouchListener);
		tvScramble.setOnLongClickListener(mOnLongClickListener);
		tvScramble.setTextColor(colors[1]);
		//tvScramble.setHeight((int)(DCTimer.dm.heightPixels*0.3));
		tvTimer = (TextView) findViewById(R.id.tv_timer);	//计时器
		tvTimer.setOnTouchListener(this);
        tvAvg = (TextView) findViewById(R.id.tv_avg);	//平均统计
		changeRealMeanPos();
		tvAvg.setTextColor(colors[1]);
		scrambleView = (ImageView) findViewById(R.id.iv_scr);	//打乱状态图
		
		//分组名称
		for (int j = 0; j < DB_TBL_COUNT; j++)
			sesItems.add((j + 1) + ". " + sesnames.get(j));
		//成绩
		tvSesName = (TextView) findViewById(R.id.sesname);
		tvSesName.setText(sesnames.get(sesIdx).equals("") ? getString(R.string.session)+(sesIdx+1) : sesnames.get(sesIdx));
		tvSesName.setTextColor(colors[1]);
		tvTxtSesName = (TextView) findViewById(R.id.txt_sesname);
		tvTxtSesName.setText(sesnames.get(sesIdx).equals("") ? getString(R.string.session)+(sesIdx+1) : sesnames.get(sesIdx));
		//成绩列表
		layoutTitle = (LinearLayout) findViewById(R.id.layout_title);
		lvTimes = (ListView) findViewById(R.id.lv_times);
		btSesMean = (Button) findViewById(R.id.bt_ses_mean);	//分组平均
		session.getSession(sesIdx, isMulp);
		btSesMean.setOnClickListener(mOnClickListener);
		btSesMean.setText(getString(R.string.session_average) + Statistics.sessionMean());
		setResultTitle();
		setListView();
		btSession = (Button) findViewById(R.id.bt_session);	//分组按钮
		btSession.setOnClickListener(mOnClickListener);
		btSesOptn = (Button) findViewById(R.id.bt_optn);	//分组选项
		btSesOptn.setOnClickListener(mOnClickListener);
		btOption = (Button)findViewById(R.id.bt_option);
		btOption.setOnClickListener(mOnClickListener);
		btOutSetting = (Button)findViewById(R.id.bt_out_setting);
		btOutSetting.setOnClickListener(mOnClickListener);
		btInSetting = (Button)findViewById(R.id.bt_in_setting);
		btInSetting.setOnClickListener(mOnClickListener);
		tvTitle = (TextView) findViewById(R.id.tv_setting);	//设置
		tvTitle.setTextColor(colors[1]);
		//设置TextView
		ids = new int[] {R.id.stt08, R.id.stt09, R.id.stt17, R.id.stt31, R.id.stt05, R.id.stt20};
		for(int i=0; i<ids.length; i++) tvSettings[i] = (TextView) findViewById(ids[i]);
		
		//设置选项
		ids = new int[] {R.id.std01, R.id.std02, R.id.std03, R.id.std04, R.id.std16, R.id.std06, R.id.std07, R.id.std08, 
				R.id.std09, R.id.std10, R.id.std11, R.id.std12, R.id.std13, R.id.std14, R.id.std15, R.id.std20, R.id.std21,
				R.id.std40, R.id.std41, R.id.std42, R.id.std43, R.id.std46, R.id.std47, R.id.std48};
		for(int i=0; i<std.length; i++) {
			std[i] = (TextView) findViewById(ids[i]);
		}
		stdn[0] = (TextView) findViewById(R.id.std17);	//平均1长度
		stdn[1] = (TextView) findViewById(R.id.std18);	//平均2长度
        stdn[2] = (TextView) findViewById(R.id.std27);
		stdn[3] = (TextView) findViewById(R.id.std44);
		stdn[4] = (TextView) findViewById(R.id.std45);
		stdn[5] = (TextView) findViewById(R.id.std50);
		stdn[6] = (TextView) findViewById(R.id.std51);
		stdn[7] = (TextView) findViewById(R.id.std52);
		stdn[8] = (TextView) findViewById(R.id.std53);
		//拖动条
		ids = new int[] {R.id.seekb1, R.id.seekb2, R.id.seekb3, R.id.seekb4, R.id.seekb5, R.id.seekb6, R.id.seekb7, R.id.seekb10};
		for(int i=0; i<ids.length; i++) {
			seekBar[i] = (SeekBar) findViewById(ids[i]);
			seekBar[i].setOnSeekBarChangeListener(mOnSeekBarChangeListener);
		}
		//设置开关
		ids = new int[] {R.id.stcheck1, R.id.stcheck15, R.id.stcheck3, R.id.stcheck12, R.id.stcheck11, R.id.stcheck6,
				R.id.stcheck7, R.id.stcheck8, R.id.stcheck9, R.id.stcheck100, R.id.stcheck40};
		for(int i=0; i<ids.length; i++) {
			ibSwitch[i] = (ImageButton) findViewById(ids[i]);
			ibSwitch[i].setOnClickListener(mOnClickListener);
		}
		
		btSolver3[0] = (Button) findViewById(R.id.solve1);	//十字底面
		btSolver3[0].setOnClickListener(mOnClickListener);
		btSolver3[1] = (Button) findViewById(R.id.solve2);	//颜色
		btSolver3[1].setOnClickListener(mOnClickListener);
		//设置Layout
		ids = new int[] {
				R.id.lay01, R.id.lay02, R.id.lay03, R.id.lay04, R.id.lay30, R.id.lay26, R.id.lay06,R.id.lay07, R.id.lay08, R.id.lay09,
				R.id.lay10, R.id.lay11, R.id.lay12, R.id.lay31, R.id.lay46, R.id.lay40, R.id.lay41, R.id.lay42, R.id.lay43, R.id.lay47,
				R.id.lay23, R.id.lay18, R.id.lay25, R.id.lay49,
				R.id.lay16, R.id.lay17, R.id.lay22, R.id.lay19, R.id.lay20, R.id.lay21,
				R.id.lay13, R.id.lay24, R.id.lay14, R.id.lay15, R.id.lay27, R.id.lay28, R.id.lay37, R.id.lay44, R.id.lay45, R.id.lay50,
				R.id.lay51, R.id.lay52, R.id.lay53
		};
		for(int i=0; i<ids.length; i++)
			llayout[i] = (RelativeLayout) findViewById(ids[i]);
		for(int i=0; i<24; i++) llayout[i].setOnClickListener(comboListener);
		for(int i=24; i<43; i++) llayout[i].setOnClickListener(mOnClickListener);
		//EG打乱
		ids = new int[] {R.id.checkcll, R.id.checkeg1, R.id.checkeg2,
				R.id.checkegpi, R.id.checkegh, R.id.checkegu, R.id.checkegt, R.id.checkegl,
				R.id.checkegs, R.id.checkega, R.id.checkegn};
		for(int i=0; i<ids.length; i++) {
			checkBox[i] = (CheckBox) findViewById(ids[i]);
			checkBox[i].setOnCheckedChangeListener(mOnCheckedChangeListener);
		}
		if((egtype & 4) != 0) checkBox[0].setChecked(true);
		if((egtype & 2) != 0) checkBox[1].setChecked(true);
		if((egtype & 1) != 0) checkBox[2].setChecked(true);
		if((egoll & 128) != 0) checkBox[3].setChecked(true);
		if((egoll & 64) != 0) checkBox[4].setChecked(true);
		if((egoll & 32) != 0) checkBox[5].setChecked(true);
		if((egoll & 16) != 0) checkBox[6].setChecked(true);
		if((egoll & 8) != 0) checkBox[7].setChecked(true);
		if((egoll & 4) != 0) checkBox[8].setChecked(true);
		if((egoll & 2) != 0) checkBox[9].setChecked(true);
		if((egoll & 1) != 0) checkBox[10].setChecked(true);
		//复位按钮
		btReset = (Button) findViewById(R.id.reset);
		btReset.setOnClickListener(mOnClickListener);
		btResetColor = (Button) findViewById(R.id.reset_color);
		btResetColor.setOnClickListener(mOnClickListener);
		//关于
		btAbout = (Button) findViewById(R.id.about);
        btAbout.setOnClickListener(mOnClickListener);
		//进度条
		progressDialog = new ProgressDialog(this);
		progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		progressDialog.setCancelable(false);
		//震动器
		vibrator = (Vibrator) getSystemService(Service.VIBRATOR_SERVICE);
		version = Utils.getVersion(context);

		if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            AudioAttributes abs = new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                    .build() ;
			soundPool = new SoundPool.Builder()
					.setMaxStreams(10)
                    .setAudioAttributes(abs)
					.build();
		} else {
			soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
		}
		soundPool.load(this, R.raw.digit1, 1);
		soundPool.load(this, R.raw.digit2, 1);
		soundPool.load(this, R.raw.digit3, 1);
		soundPool.load(this, R.raw.digit4, 1);
		soundPool.load(this, R.raw.digit5, 1);
		soundPool.load(this, R.raw.digit6, 1);
		soundPool.load(this, R.raw.digit7, 1);
		soundPool.load(this, R.raw.digit8, 1);
		soundPool.load(this, R.raw.digit9, 1);
		//timerFrag.set2ndsel();
		setViews();
		crntScrType = -64;
		set2ndsel();
        setTimerAvg();
    }

	/*
 * 在onTouch()方法中，我们调用GestureDetector的onTouchEvent()方法，将捕捉到的MotionEvent交给GestureDetector
 * 来分析是否有合适的callback函数来处理用户的手势
 */
	public boolean onTouch(View v, MotionEvent event) {
		boolean result = false;
		//Log.i("DCTimer", "==========" + event.getAction());
		if ( 0 == Timer.state )
		{
			if ( true == mGestureDetector.onTouchEvent(event) )
			{
				Timer.touch_state = 2;
				result = true;
			}
			switch ( event.getAction() )
			{
				case MotionEvent.ACTION_DOWN:
					switch ( Timer.touch_state )
					{
						case 0:
							result = mOnTouchListener.onTouch(v, event);
							Timer.touch_state = 1;
							break;

						default:
							break;
					}
					break;

				case MotionEvent.ACTION_UP:
					switch ( Timer.touch_state )
					{
						case 1:
							result = mOnTouchListener.onTouch(v, event);
							break;

						case 2:
							event.setAction(MotionEvent.ACTION_CANCEL);
							result = mOnTouchListener.onTouch(v, event);
							break;

						default:
							break;
					}

					Timer.touch_state = 0;
					break;

				default:
					result = mOnTouchListener.onTouch(v, event);
					break;
			}
		}
		else
		{
			Timer.touch_state = 0;
			result = mOnTouchListener.onTouch(v, event);
		}

		return result;
	}

	private void changeRealMeanPos()
	{
		RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) tvAvg.getLayoutParams();

		if ( 0 == avgLayout )
		{
			params.removeRule(RelativeLayout.BELOW);
			params.addRule(RelativeLayout.LEFT_OF, R.id.iv_scr);
			params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
			tvAvg.setPadding(0, 0, 0, 0);
			tvAvg.setLayoutParams(params);
		}
		else
		{
			params.removeRule(RelativeLayout.LEFT_OF);
			params.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
			params.addRule(RelativeLayout.BELOW, R.id.tv_scr);
			tvAvg.setPadding(5, 30, 5, 0);
			tvAvg.setLayoutParams(params);
		}
	}

	/**
	 * 申请权限
	 */
	public void requestRuntimePermissions(
			String[] permissions, PermissionListener listener) {
		mListener = listener;
		List<String> permissionList = new ArrayList<>();
		// 遍历每一个申请的权限，把没有通过的权限放在集合中
		for (String permission : permissions) {
			if (ContextCompat.checkSelfPermission(this, permission) !=
					PackageManager.PERMISSION_GRANTED) {
				permissionList.add(permission);
			} else {
				mListener.granted();
			}
		}
		// 申请权限
		if (!permissionList.isEmpty()) {
			ActivityCompat.requestPermissions(this,
					permissionList.toArray(new String[permissionList.size()]), 1);
		}
	}

	/**
	 * 申请后的处理
	 */
	@Override
	public void onRequestPermissionsResult(
			int requestCode, String[] permissions, int[] grantResults) {
		super.onRequestPermissionsResult(requestCode, permissions, grantResults);
		if (grantResults.length > 0) {
			List<String> deniedList = new ArrayList<>();
			// 遍历所有申请的权限，把被拒绝的权限放入集合
			for (int i = 0; i < grantResults.length; i++) {
				int grantResult = grantResults[i];
				if (grantResult == PackageManager.PERMISSION_GRANTED) {
					mListener.granted();
				} else {
					deniedList.add(permissions[i]);
				}
			}
			if (!deniedList.isEmpty()) {
				mListener.denied(deniedList);
			}
		}
	}

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
		//System.out.println("旋转屏幕");
		getWindowManager().getDefaultDisplay().getMetrics(dm);
		if(!useBgcolor) try {
			Bitmap bm = Utils.getBitmap(picPath);
			bitmap = Utils.getBackgroundBitmap(bm);
			tabHost.setBackgroundDrawable(Utils.getBackgroundDrawable(context, bitmap, opacity));
			bm.recycle();
		} catch (Exception e) {
			Toast.makeText(context, "Error: "+e.getMessage(), Toast.LENGTH_SHORT).show();
		} catch (OutOfMemoryError e) {
			Toast.makeText(context, "Error: "+e.getMessage(), Toast.LENGTH_SHORT).show();
		}
		updateGridView(0);
	}
	
	@Override
	protected void onDestroy() {
		//System.out.println("onDestroy");
		if(session != null)
			session.closeDB();
		soundPool.release();
		super.onDestroy();
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		menu.clear();
		menu.add(Menu.NONE, 0, 0, getString(R.string.menu_inscr));
		menu.add(Menu.NONE, 1, 1, getString(R.string.menu_outscr));
		menu.add(Menu.NONE, 2, 2, getString(R.string.menu_share));
		//menu.add(Menu.NONE, 3, 3, getString(R.string.menu_weibo));
		menu.add(Menu.NONE, 4, 4, getString(R.string.menu_about));
		menu.add(Menu.NONE, 5, 5, getString(R.string.menu_exit));
		return true;
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		final LayoutInflater factory;
		super.onOptionsItemSelected(item);
		switch (item.getItemId()) {
		case 0:	//导入打乱
			factory = LayoutInflater.from(context);
			int layoutId = R.layout.import_scramble;
			view = factory.inflate(layoutId, null);
			final Spinner sp = (Spinner) view.findViewById(R.id.spnScrType);
			String[] items = getResources().getStringArray(R.array.inscrStr);
			ArrayAdapter<String> adap = new ArrayAdapter<String>(context, android.R.layout.simple_spinner_item, items);
			adap.setDropDownViewResource(R.layout.spinner_dropdown_item);
			sp.setAdapter(adap);
			editText = (EditText) view.findViewById(R.id.edit_inscr);
			sp.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
				public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
					insType = position;
				}
				public void onNothingSelected(AdapterView<?> arg0) {}
			});
			new CustomDialog.Builder(context).setView(view).setTitle(R.string.menu_inscr)
			.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface di, int i) {
					Utils.hideKeyboard(editText);
					final String scrs = editText.getText().toString();
					inScr = new ArrayList<String>();
					inScrLen = 0;
					Utils.setInScr(scrs, inScr);
					if(inScr.size()>0) newScramble(crntScrType);
				}
			}).setNegativeButton(R.string.btn_cancel, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface arg0, int arg1) {
					Utils.hideKeyboard(editText);
				}
			}).show();
			Utils.showKeyboard(editText);
			break;
		case 1:	//导出打乱
			if(defPath == null) {
				Toast.makeText(context, getString(R.string.sd_not_exist), Toast.LENGTH_SHORT).show();
				break;
			}
			factory = LayoutInflater.from(context);
			layoutId = R.layout.export_scramble;
			view = factory.inflate(layoutId, null);
			final EditText et1 = (EditText) view.findViewById(R.id.edit_scrnum);
			final EditText et2 = (EditText) view.findViewById(R.id.edit_scrpath);
			final ImageButton btn = (ImageButton) view.findViewById(R.id.btn_browse);
			et1.setText("5");
			et1.setSelection(1);
			et2.setText(savePath);
			final EditText et3 = (EditText) view.findViewById(R.id.edit_scrfile);
			btn.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					selFilePath = et2.getText().toString();
					int lid = R.layout.file_selector;
					final View viewb = factory.inflate(lid, null);
					listView = (ListView) viewb.findViewById(R.id.list);
					File f = new File(selFilePath);
					selFilePath = f.exists() ? selFilePath : defPath + File.separator;
					tvPathName = (TextView) viewb.findViewById(R.id.text);
					tvPathName.setText(selFilePath);
					getFileDirs(selFilePath, false);
					listView.setOnItemClickListener(itemListener);
					new CustomDialog.Builder(context).setTitle(R.string.sel_path).setView(viewb)
					.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialoginterface, int j) {
							et2.setText(selFilePath + "/");
						}
					}).setNegativeButton(R.string.btn_cancel, null).show();
				}
			});
			new CustomDialog.Builder(context).setView(view).setTitle(getString(R.string.menu_outscr)+"("+btScramble.getText()+")")
			.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface di, int i) {
					String inp_value = et1.getText().toString();
					int numt = 0;
					if (!"".equals(inp_value)) numt = Integer.parseInt(inp_value);
					if(numt > 100) numt = 100;
					else if(numt < 1) numt = 5;
					final int num = numt;
					final String path = et2.getText().toString();
					if(!path.equals(savePath)) {
						savePath = path;
						edit.putString("scrpath", path);
						edit.commit();
					}
					final String fileName = et3.getText().toString();
					File file = new File(path+fileName);
					if(file.isDirectory()) Toast.makeText(context, getString(R.string.path_illegal), Toast.LENGTH_SHORT).show();
					else if(file.exists()) {
						new CustomDialog.Builder(context).setTitle(R.string.path_dupl)
						.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialoginterface, int j) {
								outScr(path, fileName, num);
							}
						}).setNegativeButton(R.string.btn_cancel, null).show();
					} else {
						outScr(path, fileName, num);
					}
					Utils.hideKeyboard(et1);
				}
			}).setNegativeButton(R.string.btn_cancel, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					Utils.hideKeyboard(et1);
				}
			}).show();
			Utils.showKeyboard(et1);
			break;
		case 2:	//分享
			Intent intent=new Intent(Intent.ACTION_SEND);
			intent.setType("text/plain");	//纯文本
			intent.putExtra(Intent.EXTRA_SUBJECT, "分享");
			intent.putExtra(Intent.EXTRA_TEXT, getShareContent());
			startActivity(Intent.createChooser(intent, getTitle()));
			break;
		
		case 4:	//关于
			new CustomDialog.Builder(context).setIcon(R.drawable.ic_launcher).setTitle(R.string.abt_title).setMessage(String.format(getString(R.string.abt_msg), getString(R.string.app_version)))
			.setPositiveButton(R.string.btn_upgrade, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					new Thread() {
						public void run() {
							handler.sendEmptyMessage(8);
							String ver = Utils.getContent("https://github.com/andersgong/DCTimer2.0/raw/master/release/version.txt");
							if(ver.startsWith("error")) {
								handler.sendEmptyMessage(9);
							} else {
								String[] vers = ver.split("\t");
								int v = 0;
								if (!"".equals(vers[0])) v = Integer.parseInt(vers[0]);
								if(v > version) {
									newVersion = vers[1];
									StringBuilder sb = new StringBuilder(vers[2]);
									if(vers.length > 3)
										for(int i=3; i<vers.length; i++) sb.append("\n"+vers[i]);
									updateCont = sb.toString();
									handler.sendEmptyMessage(16);
								}
								else {
									newVersion = vers[1];
									StringBuilder sb = new StringBuilder(vers[0]);
									for(int i=1; i<vers.length; i++) sb.append("\n"+vers[i]);
									updateCont = sb.toString();
									handler.sendEmptyMessage(33);
								}
							}
						}
					}.start();
				}
			})
			.setNegativeButton(R.string.btn_close, null).show();
			break;
		case 5:	//退出
			if(session != null)
				session.closeDB();
			edit.putInt("sel", scrIdx);
			edit.putInt("sel2", scr2idx);
			edit.commit();
			android.os.Process.killProcess(android.os.Process.myPid());
		}
		return true;
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (requestCode == 1) {	//设置背景图片
			if (resultCode == RESULT_OK) {
				Uri uri = data.getData();
				String[] filePathColumn = {MediaStore.Images.Media.DATA};
				//System.out.println(uri);
				//Log.i("DCTimer", "uri:" + uri.getPath());
				if("file".equalsIgnoreCase(uri.getScheme())) {
					picPath = uri.getPath();
				} else {
				    ContentResolver cr = getContentResolver();
					Cursor c = cr.query(uri, filePathColumn, null, null, null);
					c.moveToFirst();
					int columnIndex = c.getColumnIndex(filePathColumn[0]);
					picPath = c.getString(columnIndex);
					//Log.i("DCTimer", "=========path:" + picPath);
					c.close();
				}
				//System.out.println("文件路径 " + picPath);
				useBgcolor = false;
				edit.putString("picpath", picPath);
				edit.putBoolean("bgcolor", false);
				edit.commit();
				try {
					Bitmap bm = Utils.getBitmap(picPath);
					bitmap = Utils.getBackgroundBitmap(bm);
					tabHost.setBackgroundDrawable(Utils.getBackgroundDrawable(context, bitmap, opacity));
					bm.recycle();
				} catch (Exception e) {
					Toast.makeText(context, "Error: "+e.getMessage(), Toast.LENGTH_SHORT).show();
				} catch (OutOfMemoryError e) {
					Toast.makeText(context, "Out of memory error: bitmap size exceeds VM budget", Toast.LENGTH_SHORT).show();
				}
			}
		}
	}
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		switch (keyCode) {
		case KeyEvent.KEYCODE_BACK:
			//Log.d("DCTimer","====" + Timer.state + "=====" + event.getRepeatCount());
			if(Timer.state == 1) {
				if ( 0 == stSel[15] )
				{
					return true;
				}
				timer.timeEnd = System.currentTimeMillis();
				timer.count();
				setVisibility(true);
				if(!wca) {isp2 = 0; idnf = true;}
				confirmTime((int) timer.time);
				Timer.state = 0;
				if(!opnl) releaseWakeLock();
			} else if (Timer.state == 101)
			{
				Timer.state = 1;
				timer.count();
				setTimerText(Statistics.timeToString((int)timer.time));
				setVisibility(true);
				if(isLongPress) isLongPress = false;
				if(!wca) {isp2=0; idnf=true;}
				confirmTime((int)timer.time);
				Timer.state = 0;
				if(!opnl) releaseWakeLock();
			}
			else if(Timer.state == 2) {
				timer.stopInspect();
				setTimerText(stSel[2]==0 ? "0.00" : "0.000");
				setVisibility(true);
				if(!opnl) releaseWakeLock();
			} else if(event.getRepeatCount() == 0) {
				if((System.currentTimeMillis() - exitTime) > 2000) {
					Toast.makeText(context, getString(R.string.again_exit), Toast.LENGTH_SHORT).show();
					exitTime = System.currentTimeMillis();
				} else {
					edit.putInt("sel", scrIdx);
					edit.putInt("sel2", scr2idx);
					edit.commit();
		            finish();
		        }
			}
			return false;
		case KeyEvent.KEYCODE_Q:	changeScramble(-1, 10);	break;	//SQ1
		case KeyEvent.KEYCODE_W:	changeScramble(-1, 3);	break;	//二阶
		case KeyEvent.KEYCODE_E:	changeScramble(-1, 0);	break;	//三阶
		case KeyEvent.KEYCODE_R:	changeScramble(2, 0);	break;	//四阶
		case KeyEvent.KEYCODE_T:	changeScramble(-1, 2);	break;	//五阶
		case KeyEvent.KEYCODE_Y:	changeScramble(-1, 13);	break;	//六阶
		case KeyEvent.KEYCODE_U:	changeScramble(-1, 14);	break;	//七阶
		case KeyEvent.KEYCODE_M:	changeScramble(-1, 8);	break;	//五魔
		case KeyEvent.KEYCODE_P:	changeScramble(-1, 9);	break;	//金字塔
		case KeyEvent.KEYCODE_K:	changeScramble(-1, 11);	break;	//魔表
		case KeyEvent.KEYCODE_S:	changeScramble(-1, 12);	break;	//斜转
		case KeyEvent.KEYCODE_N:	newScramble(crntScrType);	break;	//新打乱
		case KeyEvent.KEYCODE_Z:	//删除最后成绩
			if(Session.length==0) Toast.makeText(context, getString(R.string.no_times), Toast.LENGTH_SHORT).show();
			else new CustomDialog.Builder(context).setTitle(R.string.confirm_del_last)
			.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					delete(Session.length-1);
				}
			}).setNegativeButton(R.string.btn_cancel, null).show();
			break;
		case KeyEvent.KEYCODE_A:	//删除所有成绩
			if(Session.length==0) Toast.makeText(context, getString(R.string.no_times), Toast.LENGTH_SHORT).show();
			else new CustomDialog.Builder(context).setTitle(R.string.confirm_clear_session)
			.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {deleteAll();}
			}).setNegativeButton(R.string.btn_cancel, null).show();
			break;
		case KeyEvent.KEYCODE_D:	//最近一次成绩
			if(Session.length==0) Toast.makeText(context, getString(R.string.no_times), Toast.LENGTH_SHORT).show();
			else new CustomDialog.Builder(context).setTitle(getString(R.string.show_time) + Statistics.timeAt(Session.length-1, true))
			.setItems(R.array.rstcon, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					switch (which) {
					case 0: update(Session.length-1, (byte) 0); break;
					case 1: update(Session.length-1, (byte) 1); break;
					case 2: update(Session.length-1, (byte) 2); break;
					}
				}
			}).setNegativeButton(getString(R.string.btn_cancel), null).show();
		}
		return super.onKeyDown(keyCode, event);
	};
	
	private OnCheckedChangeListener mOnTabChangeListener = new OnCheckedChangeListener() {
		@Override
		public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
			if(isChecked) {
				int pos = 0;
				switch (buttonView.getId()) {
				case R.id.radio_1:
					pos = 0;
					break;
				case R.id.radio_2:
					pos = 1;
					break;
				case R.id.radio_3:
					pos = 2;
					break;
				case R.id.radio_4:
					pos = 3;
					break;
				}
				tabHost.setCurrentTab(pos);
				if (0 == pos)
                {
                    currentMean();
                }
				for(int i=0; i<4; i++) {
					if(i == pos) {
						rbTab[i].setTextColor(0xff3d9ee8);
						Drawable dr = getResources().getDrawable(resId[i + 4]);
						rbTab[i].setCompoundDrawablesWithIntrinsicBounds(null, dr, null, null);
					} else {
						rbTab[i].setTextColor(0xff747474);
						Drawable dr = getResources().getDrawable(resId[i]);
						rbTab[i].setCompoundDrawablesWithIntrinsicBounds(null, dr, null, null);
					}
				}
			}
		}
	};

	private void NewSession(String name)
	{
		DB_TBL_COUNT++;
		edit.putInt("sescnt", DB_TBL_COUNT);
		edit.putInt("sestype" + (DB_TBL_COUNT-1), 32);
		edit.putString("sesname" + (DB_TBL_COUNT-1), name);
		edit.commit();

		sesType.add(share.getInt("sestype" + (DB_TBL_COUNT-1), 32));
		sesnames.add(share.getString("sesname" + (DB_TBL_COUNT-1), ""));
		sesItems.add(DB_TBL_COUNT + ". " + sesnames.get(DB_TBL_COUNT-1));
		sesAvgType1.add(0);
		sesAvgNum1.add(5);
		sesAvgType2.add(0);
		sesAvgNum2.add(12);
	}

	private void changeBackgroudColor(int color)
	{
		tabHost.setBackgroundColor(color);
		if ( 0xff66ccff == color )
		{
			tabLine.setVisibility(View.VISIBLE);
			showTabLine = true;
			rGroup.setBackgroundColor(Color.parseColor("#ccf9f9f9"));
		}
		else {
			tabLine.setVisibility(View.GONE);
			showTabLine = false;
			rGroup.setBackgroundColor(color);
		}
	}

	private int showScrToReal(int index)
	{
		for (int i = 0; i < scrAry.length && index > 0 && index < scrAryShow.length; i++ ) {
			if ( scrAry[i].equals(scrAryShow[index]) )
			{
				return i;
			}
		}
		return index;
	}

	private int realScrToShow(int index)
	{
		for (int i = 0; i < scrAryShow.length && index > 0 && index < scrAry.length; i++ ) {
			if ( scrAryShow[i].equals(scrAry[index]) )
			{
				return i;
			}
		}
		return index;
	}
	
	private View.OnClickListener mOnClickListener = new View.OnClickListener() {
		ColorPickerView colorPickerView;
		ColorSchemeView colorSchemeView;
		@Override
		public void onClick(View v) {
			final int sel = v.getId();
			final LayoutInflater factory10;
			final int layoutId10;
			switch (sel) {
				case R.id.bt_out_setting:	//导出设置
					if(defPath == null) {
						Toast.makeText(context, getString(R.string.sd_not_exist), Toast.LENGTH_SHORT).show();
						break;
					}
					factory10 = LayoutInflater.from(context);
					layoutId10 = R.layout.save_stat;
					view = factory10.inflate(layoutId10, null);
					editText = (EditText) view.findViewById(R.id.edit_scrpath);
					ImageButton btn = (ImageButton) view.findViewById(R.id.btn_browse);
					editText.setText(savePath);
					final EditText et2 = (EditText) view.findViewById(R.id.edit_scrfile);
					et2.requestFocus();
					et2.setText("settings.db");
					et2.setSelection(et2.getText().length());
					btn.setOnClickListener(new View.OnClickListener() {
						public void onClick(View v) {
							selFilePath = editText.getText().toString();
							int lid = R.layout.file_selector;
							final View viewb = factory10.inflate(lid, null);
							listView = (ListView) viewb.findViewById(R.id.list);
							File f = new File(selFilePath);
							selFilePath = f.exists() ? selFilePath : defPath + File.separator;
							tvPathName = (TextView) viewb.findViewById(R.id.text);
							tvPathName.setText(selFilePath);
							getFileDirs(selFilePath, false);
							listView.setOnItemClickListener(itemListener);
							new CustomDialog.Builder(context).setTitle(R.string.sel_path).setView(viewb)
									.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
										public void onClick(DialogInterface dialoginterface, int j) {
											editText.setText(selFilePath+"/");
										}
									}).setNegativeButton(R.string.btn_cancel, null).show();
						}
					});
					new CustomDialog.Builder(context).setView(view).setTitle(R.string.out_setting)
							.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface di, int i) {
									final String path = editText.getText().toString();
									if(!path.equals(savePath)) {
										savePath = path;
										edit.putString("scrpath", path);
										edit.commit();
									}
									final String fileName = et2.getText().toString();
									File file = new File(path+fileName);
									if(file.isDirectory()) Toast.makeText(context, getString(R.string.path_illegal), Toast.LENGTH_SHORT).show();
									else if(file.exists()) {
										new CustomDialog.Builder(context).setTitle(R.string.path_dupl)
												.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
													public void onClick(DialogInterface dialoginterface, int k) {
														exportSettings(path+fileName);
													}
												}).setNegativeButton(R.string.btn_cancel, null).show();
									} else exportSettings(path+fileName);
									Utils.hideKeyboard(editText);
								}
							}).setNegativeButton(R.string.btn_cancel, new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface arg0, int arg1) {
									Utils.hideKeyboard(editText);
								}
							}).show();
					break;
				case R.id.bt_in_setting:	//导入设置
					if(defPath == null) {
						Toast.makeText(context, getString(R.string.sd_not_exist), Toast.LENGTH_SHORT).show();
						break;
					}
					factory10 = LayoutInflater.from(context);
					layoutId10 = R.layout.import_db;
					view = factory10.inflate(layoutId10, null);
					editText = (EditText) view.findViewById(R.id.edit_scrpath);
					btn = (ImageButton) view.findViewById(R.id.btn_browse);
					editText.setText(savePath+"settings.db");
					editText.setSelection(editText.getText().length());
					btn.setOnClickListener(new View.OnClickListener() {
						public void onClick(View v) {
							selFilePath = editText.getText().toString();
							selFilePath = selFilePath.substring(0, selFilePath.lastIndexOf('/'));
							int lid = R.layout.file_selector;
							final View viewb = factory10.inflate(lid, null);
							listView = (ListView) viewb.findViewById(R.id.list);
							File f = new File(selFilePath);
							selFilePath = f.exists() ? selFilePath : Environment.getExternalStorageDirectory().getPath()+File.separator;
							tvPathName = (TextView) viewb.findViewById(R.id.text);
							tvPathName.setText(selFilePath);
							getFileDirs(selFilePath, true);
							final CustomDialog fdialog = new CustomDialog.Builder(context).setTitle(R.string.sel_path).setView(viewb)
									.setNegativeButton(R.string.btn_close, null).create();
							listView.setOnItemClickListener(new OnItemClickListener() {
								@Override
								public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
									selFilePath = paths.get(arg2);
									File f = new File(selFilePath);
									if(f.isDirectory()) {
										tvPathName.setText(selFilePath);
										getFileDirs(selFilePath, true);
									} else {
										editText.setText(selFilePath);
										fdialog.dismiss();
									}
								}
							});
							fdialog.show();
						}
					});
					new CustomDialog.Builder(context).setView(view).setTitle(R.string.in_setting)
							.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface di, int i) {
									Utils.hideKeyboard(editText);
									final String path = editText.getText().toString();
									File file = new File(path);
									if(file.isDirectory()) Toast.makeText(context, getString(R.string.path_illegal), Toast.LENGTH_SHORT).show();
									else if(file.exists()) {
										importSettings(path);
									} else Toast.makeText(context, getString(R.string.file_not_exist), Toast.LENGTH_SHORT).show();
								}
							}).setNegativeButton(R.string.btn_cancel, new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface arg0, int arg1) {
									Utils.hideKeyboard(editText);
								}
							}).show();
				break;
			case R.id.bt_scr:	//选择打乱
				selScr1 = scrIdx;
				selScr2 = scr2idx;
				int resId = R.layout.pop_window;
				int showId = realScrToShow(selScr1+1);
				view = LayoutInflater.from(context).inflate(resId, null);
				listView = (ListView) view.findViewById(R.id.list1);
				scr1Adapter = new TextAdapter(context, scrAryShow, showId, 1);
				listView.setAdapter(scr1Adapter);
				listView.setSelection(showId);
				listView.setOnItemClickListener(itemListener);
				listView = (ListView) view.findViewById(R.id.list2);
				scr2Adapter = new TextAdapter(context, getResources().getStringArray(Utils.get2ndScr(scrIdx)), selScr2, 2);
				listView.setAdapter(scr2Adapter);
				listView.setSelection(selScr2);
				listView.setOnItemClickListener(itemListener);
				popupWindow = new PopupWindow(view, dip300, dip300, true);
				popupWindow.setBackgroundDrawable(getResources().getDrawable(R.drawable.choosearea_bg_mid));
				popupWindow.setTouchable(true);
				popupWindow.showAsDropDown(v, (btScramble.getWidth()-popupWindow.getWidth())/2, 0);
				break;
			case R.id.bt_session:	//选择分组
				CharSequence[] tempSes = new CharSequence[sesItems.size()];
				CharSequence[] tempSes2 = new CharSequence[sesItems.size()];
				int tempId = sesIdx;
				sesItems.toArray(tempSes);
				for ( int k = 0; k < sesItems.size(); k++ )
				{
					session.getSession(k, isMulp);
					if ( 0 < session.getLength() )
					{
						tempSes2[k] = getString(R.string.stat_mean) + "(" + Statistics.sessionMean();
					}
					else
					{
						tempSes2[k] = getString(R.string.stat_mean) + "(0/0)";
					}
				}
				sesIdx = tempId;
				session.getSession(sesIdx, isMulp);
				new CustomDialog.Builder(context).setSingleChoiceItems2(tempSes, tempSes2, sesIdx, new OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						if(sesIdx != which) {
							sesIdx = which;
							session.getSession(which, isMulp);
							btSesMean.setText(getString(R.string.session_average) + Statistics.sessionMean());
							setListView();
							edit.putInt("group", sesIdx);
							edit.commit();
							tvSesName.setText((sesnames.get(sesIdx).equals("") ? getString(R.string.session) + (sesIdx+1) : sesnames.get(sesIdx)));
							tvTxtSesName.setText((sesnames.get(sesIdx).equals("") ? getString(R.string.session) + (sesIdx+1) : sesnames.get(sesIdx)));
							if(selScr && sesType.get(which) != crntScrType) {
								scrIdx = sesType.get(which) >> 5;
								scr2idx = sesType.get(which) & 31;
                                edit.putInt("sel", scrIdx);
                                edit.putInt("sel2", scr2idx);
                                edit.commit();
                                set2ndsel();
							}
							if ( sesIdx < sesAvgType1.size() )
							{
								stSel[14] = sesAvgType1.get(sesIdx);
								stSel[4] = sesAvgType2.get(sesIdx);
								l1len = sesAvgNum1.get(sesIdx);
								l2len = sesAvgNum2.get(sesIdx);
								std[4].setText(itemStr[4][stSel[4]]);
								std[14].setText(itemStr[14][stSel[14]]);
								stdn[0].setText(""+l1len);
								stdn[1].setText(""+l2len);

								if(!isMulp) setResultTitle();
								if(Session.length>0 && !isMulp) {
									setResultTitle();
									updateGridView(1);
								}
							}
						}
						dialog.dismiss();
					}
				}).setNegativeButton(R.string.btn_close, null).show();
				break;
			case R.id.bt_option: //选项
				new CustomDialog.Builder(context).setItems(R.array.optScrStr, new OnClickListener() {
					ImageView iv;
					LayoutInflater factory;
					@Override
					public void onClick(DialogInterface dialog, int which) {
						switch (which) {
							case 0:	//导入打乱
								factory = LayoutInflater.from(context);
								int layoutId = R.layout.import_scramble;
								view = factory.inflate(layoutId, null);
								final Spinner sp = (Spinner) view.findViewById(R.id.spnScrType);
								String[] items = getResources().getStringArray(R.array.inscrStr);
								ArrayAdapter<String> adap = new ArrayAdapter<String>(context, android.R.layout.simple_spinner_item, items);
								adap.setDropDownViewResource(R.layout.spinner_dropdown_item);
								sp.setAdapter(adap);
								editText = (EditText) view.findViewById(R.id.edit_inscr);
								sp.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
									public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
										insType = position;
									}
									public void onNothingSelected(AdapterView<?> arg0) {}
								});
								new CustomDialog.Builder(context).setView(view).setTitle(R.string.menu_inscr)
										.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
											public void onClick(DialogInterface di, int i) {
												Utils.hideKeyboard(editText);
												final String scrs = editText.getText().toString();
												inScr = new ArrayList<String>();
												inScrLen = 0;
												Utils.setInScr(scrs, inScr);
												if(inScr.size()>0) newScramble(crntScrType);
											}
										}).setNegativeButton(R.string.btn_cancel, new DialogInterface.OnClickListener() {
									public void onClick(DialogInterface arg0, int arg1) {
										Utils.hideKeyboard(editText);
									}
								}).show();
								Utils.showKeyboard(editText);
								break;
							case 1:	//导出打乱
								if(defPath == null) {
									Toast.makeText(context, getString(R.string.sd_not_exist), Toast.LENGTH_SHORT).show();
									break;
								}
								factory = LayoutInflater.from(context);
								layoutId = R.layout.export_scramble;
								view = factory.inflate(layoutId, null);
								final EditText et1 = (EditText) view.findViewById(R.id.edit_scrnum);
								final EditText et2 = (EditText) view.findViewById(R.id.edit_scrpath);
								final ImageButton btn = (ImageButton) view.findViewById(R.id.btn_browse);
								et1.setText("5");
								et1.setSelection(1);
								et2.setText(savePath);
								final EditText et3 = (EditText) view.findViewById(R.id.edit_scrfile);
								btn.setOnClickListener(new View.OnClickListener() {
									@Override
									public void onClick(View v) {
										selFilePath = et2.getText().toString();
										int lid = R.layout.file_selector;
										final View viewb = factory.inflate(lid, null);
										listView = (ListView) viewb.findViewById(R.id.list);
										File f = new File(selFilePath);
										selFilePath = f.exists() ? selFilePath : defPath + File.separator;
										tvPathName = (TextView) viewb.findViewById(R.id.text);
										tvPathName.setText(selFilePath);
										getFileDirs(selFilePath, false);
										listView.setOnItemClickListener(itemListener);
										new CustomDialog.Builder(context).setTitle(R.string.sel_path).setView(viewb)
												.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
													public void onClick(DialogInterface dialoginterface, int j) {
														et2.setText(selFilePath + "/");
													}
												}).setNegativeButton(R.string.btn_cancel, null).show();
									}
								});
								new CustomDialog.Builder(context).setView(view).setTitle(getString(R.string.menu_outscr)+"("+btScramble.getText()+")")
										.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
											public void onClick(DialogInterface di, int i) {
												String inp_value = et1.getText().toString();
												int numt = 0;
												if (!"".equals(inp_value)) numt = Integer.parseInt(inp_value);
												if(numt > 100) numt = 100;
												else if(numt < 1) numt = 5;
												final int num = numt;
												final String path = et2.getText().toString();
												if(!path.equals(savePath)) {
													savePath = path;
													edit.putString("scrpath", path);
													edit.commit();
												}
												final String fileName = et3.getText().toString();
												File file = new File(path+fileName);
												if(file.isDirectory()) Toast.makeText(context, getString(R.string.path_illegal), Toast.LENGTH_SHORT).show();
												else if(file.exists()) {
													new CustomDialog.Builder(context).setTitle(R.string.path_dupl)
															.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
																public void onClick(DialogInterface dialoginterface, int j) {
																	outScr(path, fileName, num);
																}
															}).setNegativeButton(R.string.btn_cancel, null).show();
												} else {
													outScr(path, fileName, num);
												}
												Utils.hideKeyboard(et1);
											}
										}).setNegativeButton(R.string.btn_cancel, new DialogInterface.OnClickListener() {
									public void onClick(DialogInterface dialog, int which) {
										Utils.hideKeyboard(et1);
									}
								}).show();
								Utils.showKeyboard(et1);
								break;
							case 2:	//找插入
								//tabHost.setCurrentTab(3);
								//tabHost.getCurrentTabView().requestFocus();
								if (null != if_web && !"".equals(if_web)) {
									rbTab[3].setChecked(true);
									webView.loadUrl(if_web);
								}
								break;
							case 3:	//找插入
								//tabHost.setCurrentTab(3);
								//tabHost.getCurrentTabView().requestFocus();
								if (null != alg_web1 && !"".equals(alg_web1)) {
									rbTab[3].setChecked(true);
									webView.loadUrl(alg_web1);
								}
								break;
							case 4:	//找插入
								//tabHost.setCurrentTab(3);
								//tabHost.getCurrentTabView().requestFocus();
								if (null != alg_web2 && !"".equals(alg_web2)) {
									rbTab[3].setChecked(true);
									webView.loadUrl(alg_web2);
								}
								break;
							case 5:	//找插入
								//tabHost.setCurrentTab(3);
								//tabHost.getCurrentTabView().requestFocus();
								if (null != alg_web3 && !"".equals(alg_web3)) {
									rbTab[3].setChecked(true);
									webView.loadUrl(alg_web3);
								}
								break;
							case 6:	//分享
								factory = LayoutInflater.from(context);
								int layoutId2 = R.layout.ses_name;
								view = factory.inflate(layoutId2, null);
								editText = (EditText) view.findViewById(R.id.edit_ses);
								editText.setText(getShareContent());
								new CustomDialog.Builder(context).setTitle(R.string.stt_share).setView(view)
										.setPositiveButton(R.string.stt_share, new DialogInterface.OnClickListener() {
											public void onClick(DialogInterface dialog, int which) {
												Intent intent=new Intent(Intent.ACTION_SEND);
												intent.setType("text/plain");	//纯文本
												intent.putExtra(Intent.EXTRA_SUBJECT, "分享");
												intent.putExtra(Intent.EXTRA_TEXT, editText.getText().toString());
												startActivity(Intent.createChooser(intent, getTitle()));
											}
										}).setNegativeButton(R.string.btn_cancel, new OnClickListener() {
											public void onClick(DialogInterface dialog, int which) {
												Utils.hideKeyboard(editText);
											}
										}).show();
								Utils.showKeyboard(editText);
								break;
							case 7:	//关于
								new CustomDialog.Builder(context).setIcon(R.drawable.ic_launcher).setTitle(R.string.abt_title).setMessage(String.format(getString(R.string.abt_msg), getString(R.string.app_version)))
										.setPositiveButton(R.string.btn_upgrade, new DialogInterface.OnClickListener() {
											public void onClick(DialogInterface dialog, int which) {
												new Thread() {
													public void run() {
														handler.sendEmptyMessage(8);
														String ver = Utils.getContent("https://github.com/andersgong/DCTimer2.0/raw/master/release/version.txt");
														if(ver.startsWith("error")) {
															handler.sendEmptyMessage(9);
														} else {
															String[] vers = ver.split("\t");
															int v = 0;
															if (!"".equals(vers[0])) v = Integer.parseInt(vers[0]);
															if(v > version) {
																newVersion = vers[1];
																StringBuilder sb = new StringBuilder(vers[2]);
																if(vers.length > 3)
																	for(int i=3; i<vers.length; i++) sb.append("\n"+vers[i]);
																updateCont = sb.toString();
																handler.sendEmptyMessage(16);
															}
															else {
																newVersion = vers[1];
																StringBuilder sb = new StringBuilder(vers[0]);
																for(int i=1; i<vers.length; i++) sb.append("\n"+vers[i]);
																updateCont = sb.toString();
																handler.sendEmptyMessage(33);
															}
														}
													}
												}.start();
											}
										}).setNegativeButton(R.string.btn_close, null).show();
								break;
							case 8:	//退出
								if(session != null)
									session.closeDB();
								edit.putInt("sel", scrIdx);
								edit.putInt("sel2", scr2idx);
								edit.commit();
								android.os.Process.killProcess(android.os.Process.myPid());
						}
						}
					}).setNegativeButton(R.string.btn_close, null).show();
				break;
			case R.id.bt_optn:	//分组选项
				new CustomDialog.Builder(context).setItems(R.array.optStr, new OnClickListener() {
					ImageView iv;
					LayoutInflater factory;
					@Override
					public void onClick(DialogInterface dialog, int which) {
						switch (which) {
						case 0:	//分组命名
							factory = LayoutInflater.from(context);
							int layoutId = R.layout.ses_name;
							view = factory.inflate(layoutId, null);
							editText = (EditText) view.findViewById(R.id.edit_ses);
							editText.setText(sesnames.get(sesIdx));
							editText.setSelection(sesnames.get(sesIdx).length());
							new CustomDialog.Builder(context).setTitle(R.string.sesname).setView(view)
							.setPositiveButton(R.string.btn_ok, new OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog, int which) {
									sesnames.set(sesIdx, editText.getText().toString());
									edit.putString("sesname" + sesIdx, sesnames.get(sesIdx));
									edit.commit();
									sesItems.set(sesIdx, (sesIdx + 1) + ". " + sesnames.get(sesIdx));
									tvSesName.setText((sesnames.get(sesIdx).equals("")) ? getString(R.string.session) + (sesIdx+1) : sesnames.get(sesIdx));
									tvTxtSesName.setText((sesnames.get(sesIdx).equals("")) ? getString(R.string.session) + (sesIdx+1) : sesnames.get(sesIdx));
									Utils.hideKeyboard(editText);
								}
							}).setNegativeButton(R.string.btn_cancel, new OnClickListener() {
								public void onClick(DialogInterface dialog, int which) {
									Utils.hideKeyboard(editText);
								}
							}).show();
							Utils.showKeyboard(editText);
							break;
						case 1: //新建分组
							if ( 50 <= DB_TBL_COUNT ) break;
							factory = LayoutInflater.from(context);
							int curlen = DB_TBL_COUNT + 1;
							String sesname = context.getText(R.string.session) + "" + curlen;
							view = factory.inflate(R.layout.ses_name, null);
							editText = (EditText) view.findViewById(R.id.edit_ses);
							editText.setText(sesname);
							editText.setSelection(sesname.length());
							new CustomDialog.Builder(context).setTitle(R.string.sesadd).setView(view)
									.setPositiveButton(R.string.btn_ok, new OnClickListener() {
										@Override
										public void onClick(DialogInterface dialog, int which) {
											session.NewSession();
											NewSession(editText.getText().toString());
											Utils.hideKeyboard(editText);
										}
									}).setNegativeButton(R.string.btn_cancel, new OnClickListener() {
								public void onClick(DialogInterface dialog, int which) {
									Utils.hideKeyboard(editText);
								}
							}).show();
							Utils.showKeyboard(editText);
							break;
						case 2: //删除分组
							CharSequence[] tempSes = new CharSequence[sesItems.size()];
							sesItems.toArray(tempSes);
							delSesId = new int[tempSes.length];
							new CustomDialog.Builder(context).setMultiChoiceItems(tempSes, new OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog, int which) {
									delSesId[which] = 1 - delSesId[which];
								}
							}).setPositiveButton(R.string.delete_time, new OnClickListener() {
								public void onClick(DialogInterface dialog, int arg1) {
									deleteSelectSes();
									dialog.dismiss();
								}
							}).setNegativeButton(R.string.btn_close, null).show();
							break;
						case 3: //搜索成绩
							if(Session.length == 0) Toast.makeText(context, getString(R.string.no_times), Toast.LENGTH_SHORT).show();
							else {
								factory = LayoutInflater.from(context);
								layoutId = R.layout.number_input;
								view = factory.inflate(layoutId, null);
								editText = (EditText) view.findViewById(R.id.edit_text);
								new CustomDialog.Builder(context).setTitle(R.string.sessearch).setView(view)
										.setPositiveButton(R.string.btn_ok, new OnClickListener() {
											@Override
											public void onClick(DialogInterface dialog, int which) {
												matchIdx = -1;
												for (int i = 0; null != editText.getText().toString() && i < Session.length; i++) {
													if ( editText.getText().toString().equals(Statistics.timeAt(i, false)) )
													{
														matchIdx = i;
														break;
													}
												}
												Utils.hideKeyboard(editText);
												updateGridView(1);
											}
										}).setNegativeButton(R.string.btn_cancel, new OnClickListener() {
									public void onClick(DialogInterface dialog, int which) {
										Utils.hideKeyboard(editText);
									}
								}).show();
								Utils.showKeyboard(editText);
							}
							break;
						case 4:	//清空成绩
							if(Session.length == 0) Toast.makeText(context, getString(R.string.no_times), Toast.LENGTH_SHORT).show();
							else {
								new CustomDialog.Builder(context).setTitle(R.string.confirm_clear_session)
								.setNegativeButton(R.string.btn_cancel, null)
								.setPositiveButton(R.string.btn_ok, new OnClickListener() {
									public void onClick(DialogInterface arg0, int arg1) {
										deleteAll();
									}
								}).show();
							}
							break;
						case 5:	//时间分布直方图
							factory = LayoutInflater.from(context);
							layoutId = R.layout.graph;
							view = factory.inflate(layoutId, null);
							iv = (ImageView) view.findViewById(R.id.image_view);
							Bitmap bm = Bitmap.createBitmap(dip300, (int)(dip300*1.2), Config.ARGB_8888);
							Canvas c = new Canvas(bm);
							c.drawColor(0);
							Paint p = new Paint();
							p.setAntiAlias(true);
							Graph.drawHist(dip300, p, c);
							iv.setImageBitmap(bm);
							new CustomDialog.Builder(context).setView(view)
								.setNegativeButton(R.string.btn_close, null).show();
							break;
						case 6:	//折线图
							factory = LayoutInflater.from(context);
							layoutId = R.layout.graph;
							view = factory.inflate(layoutId, null);
							iv = (ImageView) view.findViewById(R.id.image_view);
							bm = Bitmap.createBitmap(dip300, (int)(dip300*0.9), Config.ARGB_8888);
							c = new Canvas(bm);
							//c.drawColor(0);
							p = new Paint();
							p.setAntiAlias(true);
							Graph.drawGraph(dip300, p, c);
							iv.setImageBitmap(bm);
							new CustomDialog.Builder(context).setView(view)
								.setNegativeButton(R.string.btn_close, null).show();
							break;
						case 7:	//导出数据库
							if(defPath == null) {
								Toast.makeText(context, getString(R.string.sd_not_exist), Toast.LENGTH_SHORT).show();
								break;
							}
							factory = LayoutInflater.from(context);
							layoutId = R.layout.save_stat;
							view = factory.inflate(layoutId, null);
							editText = (EditText) view.findViewById(R.id.edit_scrpath);
							ImageButton btn = (ImageButton) view.findViewById(R.id.btn_browse);
							editText.setText(savePath);
							final EditText et2 = (EditText) view.findViewById(R.id.edit_scrfile);
							et2.requestFocus();
							et2.setText("database.db");
							et2.setSelection(et2.getText().length());
							btn.setOnClickListener(new View.OnClickListener() {
								public void onClick(View v) {
									selFilePath = editText.getText().toString();
									int lid = R.layout.file_selector;
									final View viewb = factory.inflate(lid, null);
									listView = (ListView) viewb.findViewById(R.id.list);
									File f = new File(selFilePath);
									selFilePath = f.exists() ? selFilePath : defPath + File.separator;
									tvPathName = (TextView) viewb.findViewById(R.id.text);
									tvPathName.setText(selFilePath);
									getFileDirs(selFilePath, false);
									listView.setOnItemClickListener(itemListener);
									new CustomDialog.Builder(context).setTitle(R.string.sel_path).setView(viewb)
									.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
										public void onClick(DialogInterface dialoginterface, int j) {
											editText.setText(selFilePath+"/");
										}
									}).setNegativeButton(R.string.btn_cancel, null).show();
								}
							});
							new CustomDialog.Builder(context).setView(view).setTitle(R.string.out_db)
							.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface di, int i) {
									final String path = editText.getText().toString();
									if(!path.equals(savePath)) {
										savePath = path;
										edit.putString("scrpath", path);
										edit.commit();
									}
									final String fileName = et2.getText().toString();
									File file = new File(path+fileName);
									if(file.isDirectory()) Toast.makeText(context, getString(R.string.path_illegal), Toast.LENGTH_SHORT).show();
									else if(file.exists()) {
										new CustomDialog.Builder(context).setTitle(R.string.path_dupl)
										.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
											public void onClick(DialogInterface dialoginterface, int k) {
												exportDB(path+fileName);
											}
										}).setNegativeButton(R.string.btn_cancel, null).show();
									} else exportDB(path+fileName);
									Utils.hideKeyboard(editText);
								}
							}).setNegativeButton(R.string.btn_cancel, new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface arg0, int arg1) {
									Utils.hideKeyboard(editText);
								}
							}).show();
							break;
						case 8:	//导入数据库
							if(defPath == null) {
								Toast.makeText(context, getString(R.string.sd_not_exist), Toast.LENGTH_SHORT).show();
								break;
							}
							factory = LayoutInflater.from(context);
							layoutId = R.layout.import_db;
							view = factory.inflate(layoutId, null);
							editText = (EditText) view.findViewById(R.id.edit_scrpath);
							btn = (ImageButton) view.findViewById(R.id.btn_browse);
							editText.setText(savePath+"database.db");
							editText.setSelection(editText.getText().length());
							btn.setOnClickListener(new View.OnClickListener() {
								public void onClick(View v) {
									selFilePath = editText.getText().toString();
									selFilePath = selFilePath.substring(0, selFilePath.lastIndexOf('/'));
									int lid = R.layout.file_selector;
									final View viewb = factory.inflate(lid, null);
									listView = (ListView) viewb.findViewById(R.id.list);
									File f = new File(selFilePath);
									selFilePath = f.exists() ? selFilePath : Environment.getExternalStorageDirectory().getPath()+File.separator;
									tvPathName = (TextView) viewb.findViewById(R.id.text);
									tvPathName.setText(selFilePath);
									getFileDirs(selFilePath, true);
									final CustomDialog fdialog = new CustomDialog.Builder(context).setTitle(R.string.sel_path).setView(viewb)
											.setNegativeButton(R.string.btn_close, null).create();
									listView.setOnItemClickListener(new OnItemClickListener() {
										@Override
										public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
											selFilePath = paths.get(arg2);
											File f = new File(selFilePath);
											if(f.isDirectory()) {
												tvPathName.setText(selFilePath);
												getFileDirs(selFilePath, true);
											} else {
												editText.setText(selFilePath);
												fdialog.dismiss();
											}
										}
									});
									fdialog.show();
								}
							});
							new CustomDialog.Builder(context).setView(view).setTitle(R.string.in_db)
							.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface di, int i) {
									Utils.hideKeyboard(editText);
									final String path = editText.getText().toString();
									File file = new File(path);
									if(file.isDirectory()) Toast.makeText(context, getString(R.string.path_illegal), Toast.LENGTH_SHORT).show();
									else if(file.exists()) {
										importDB(path);
									} else Toast.makeText(context, getString(R.string.file_not_exist), Toast.LENGTH_SHORT).show();
								}
							}).setNegativeButton(R.string.btn_cancel, new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface arg0, int arg1) {
									Utils.hideKeyboard(editText);
								}
							}).show();
						}
					}
				}).setNegativeButton(R.string.btn_close, null).show();
				break;
			case R.id.bt_ses_mean:	//分组平均
				for(int i=0; i<Session.length; i++)
					if(Session.penalty[i] != 2) {
						showAlertDialog(3, 0);
						break;
					}
				break;
			case R.id.stcheck1:	//WCA观察
				wca = !wca;
				setSwitchOn(ibSwitch[0], wca);
				edit.putBoolean("wca", wca);
				edit.commit();
				break;
			case R.id.stcheck40:	//WCA观察
				stt_inspect = !stt_inspect;
				setSwitchOn(ibSwitch[10], stt_inspect);
				edit.putBoolean("stt_inspect", stt_inspect);
				edit.commit();
				break;
            case R.id.stcheck100:	//实时显示平均
                realMean = !realMean;
                setSwitchOn(ibSwitch[9], realMean);
                setRealMean(realMean);
                edit.putBoolean("realmean", realMean);
                edit.commit();
                break;
			case R.id.stcheck3:	//模拟ss计时
				simulateSS = !simulateSS;
				setSwitchOn(ibSwitch[2], simulateSS);
				edit.putBoolean("simss", simulateSS);
				edit.commit();
				break;
			case R.id.stcheck6:	//显示打乱状态
				showscr = !showscr;
				setSwitchOn(ibSwitch[5], showscr);
				edit.putBoolean("showscr", showscr);
				if (showscr) {
					scrambleView.setVisibility(View.VISIBLE);
					showScramble();
				}
				else scrambleView.setVisibility(View.GONE);
				edit.commit();
				break;
			case R.id.stcheck7:	//确认时间
				conft = !conft;
				setSwitchOn(ibSwitch[6], conft);
				edit.putBoolean("conft", conft);
				edit.commit();
				break;
			case R.id.stcheck8:	//成绩详情隐藏打乱
				setSwitchOn(ibSwitch[7], hidls);
				hidls = !hidls;
				edit.putBoolean("hidls", hidls);
				edit.commit();
				break;
			case R.id.stcheck9:	//自动选择打乱
				selScr = !selScr;
				setSwitchOn(ibSwitch[8], selScr);
				edit.putBoolean("selses", selScr);
				edit.commit();
				break;
			case R.id.stcheck11:	//全屏显示
				fullScreen = !fullScreen;
				setFullScreen(fullScreen);
				setSwitchOn(ibSwitch[4], fullScreen);
				edit.putBoolean("fulls", fullScreen);
				edit.commit();
				break;
			case R.id.stcheck12:	//屏幕常亮
				if(opnl) {
					if(Timer.state != 1) releaseWakeLock();
				} else acquireWakeLock();
				opnl = !opnl;
				setSwitchOn(ibSwitch[3], opnl);
				edit.putBoolean("scron", opnl);
				edit.commit();
				break;
			case R.id.stcheck15:	//等宽打乱字体
				monoscr = !monoscr;
				setSwitchOn(ibSwitch[1], monoscr);
				edit.putBoolean("monoscr", monoscr);
				edit.commit();
				setScrambleFont(monoscr ? 0 : 1);
				break;
			case R.id.solve1:	//三阶求解底面
				new CustomDialog.Builder(context).setSingleChoiceItems(R.array.faceStr, solSel[0], new OnClickListener(){
					@Override
					public void onClick(DialogInterface dialog, int which) {
						if(solSel[0] != which) {
							solSel[0] = which;
							btSolver3[0].setText(sol31[solSel[0]]);
							edit.putInt("cface", solSel[0]);
							edit.commit();
							if(stSel[5] != 0 &&
									(scrIdx==-1 && (scr2idx==0 || scr2idx==5 || scr2idx==6 || scr2idx==7) ||
									scrIdx==1 && (scr2idx==0 || scr2idx==1 || scr2idx==5 || scr2idx==19)))
								new Thread() {
								public void run() {
									handler.sendEmptyMessage(4);
									scrambler.extSol3(1, scrambler.crntScr);
									extsol = scrambler.sc;
									handler.sendEmptyMessage(3);
									scrState = NEXTSCRING;
									scrambler.extSol3(1, nextScr);
									scrState = SCRDONE;
								}
							}.start();
						}
						dialog.dismiss();
					}
				}).setNegativeButton(R.string.btn_close, null).show();
				break;
			case R.id.solve2:	//三阶求解底色
				new CustomDialog.Builder(context).setSingleChoiceItems(R.array.sideStr, solSel[1], new OnClickListener(){
					@Override
					public void onClick(DialogInterface dialog, int which) {
						if(solSel[1] != which) {
							solSel[1] = which;
							btSolver3[1].setText(sol32[solSel[1]]);
							edit.putInt("cside", solSel[1]);
							edit.commit();
							if(stSel[5] != 0 &&
									(scrIdx==-1 && (scr2idx==0 || scr2idx==5 || scr2idx==6 || scr2idx==7) ||
									scrIdx==1 && (scr2idx==0 || scr2idx==1 || scr2idx==5 || scr2idx==19)))
								new Thread() {
								public void run() {
									handler.sendEmptyMessage(4);
									scrambler.extSol3(stSel[5], scrambler.crntScr);
									extsol = scrambler.sc;
									handler.sendEmptyMessage(3);
									scrState = NEXTSCRING;
									scrambler.extSol3(stSel[5], nextScr);
									scrState = SCRDONE;
								}
							}.start();
						}
						dialog.dismiss();
					}
				}).setNegativeButton(R.string.btn_close, null).show();
				break;
			case R.id.reset:	//恢复默认设置 TODO
				new CustomDialog.Builder(context).setTitle(R.string.confirm_reset)
				.setPositiveButton(R.string.btn_ok, new OnClickListener() {
					@Override
					public void onClick(DialogInterface arg0, int arg1) {
						Language = 0;
						if(fullScreen) setFullScreen(false);
						wca=false; simulateSS=false; monoscr = false; realMean = false;
						showscr=true; conft=true; hidls=false; selScr=true; fullScreen=false;
						useBgcolor=true; opnl=false; isMulp=false;
						solSel[0]=0; solSel[1]=1;
						stSel[0]=0; stSel[1]=0; stSel[2]=1; stSel[3]=0; stSel[4]=0;
						stSel[5]=0; stSel[6]=0; stSel[7]=1; stSel[8]=3; stSel[9]=0;
						stSel[10]=0; stSel[11]=2; stSel[12]=0; stSel[15] = 0; stSel[16] = 0;
						stSel[17]= 1; stSel[18]= 2; stSel[19]= 3; stSel[20]= 4; stSel[22]=0;
						ges_left = 1; ges_right = 2; ges_up = 3; ges_down = 4; ges_double = 0;
						ges_dist = 500; ges_speed = 200;
						scrambleSize = 18; timerSize = 60; realmeanSize = 18;
						l1len = 5; l2len = 12; stt_inspect = false;
						inspprompt = 0; avgLayout = 0; prompt_time = 2;
						rowSpacing = 25; freezeTime = 0;
						colors[0] = 0xff66ccff;	colors[1] = 0xff000000;	colors[2] = 0xffff00ff;
						colors[3] = 0xffff0000;	colors[4] = 0xff009900;
						if_web = "https://fewestmov.es/";
						alg_web1 = "http://algdb.net/";
						alg_web2 = "https://algs.cuber.pro/";
						alg_web3 = null;
						changeBackgroudColor(colors[0]);
						changeRealMeanPos();
						setViews();
						setTextsColor();
						updateGridView(1);
						releaseWakeLock();
						removeConf();
						forceReboot();
					}
				}).setNegativeButton(R.string.btn_cancel, null).show();
				break;
			case R.id.reset_color:	//恢复默认配色
				new CustomDialog.Builder(context).setTitle(R.string.confirm_reset)
						.setPositiveButton(R.string.btn_ok, new OnClickListener() {
							@Override
							public void onClick(DialogInterface arg0, int arg1) {
								if(fullScreen) setFullScreen(false);
								useBgcolor=true;
								edit.putBoolean("bgcolor", useBgcolor);	//使用背景颜色
								colors[0] = 0xff66ccff;	colors[1] = 0xff000000;	colors[2] = 0xffff00ff;
								colors[3] = 0xffff0000;	colors[4] = 0xff009900;
								edit.putInt("cl0", colors[0]);	// 背景颜色
								edit.putInt("cl1", colors[1]);	// 文字颜色
								edit.putInt("cl2", colors[2]);	//最快单次颜色
								edit.putInt("cl3", colors[3]);	//最慢单次颜色
								edit.putInt("cl4", colors[4]);	//最快平均颜色
								changeBackgroudColor(colors[0]);
								setViews();
								setTextsColor();
								updateGridView(1);
								releaseWakeLock();
								forceReboot();
							}
						}).setNegativeButton(R.string.btn_cancel, null).show();
				break;
            case R.id.about:	//关于
                new CustomDialog.Builder(context).setIcon(R.drawable.ic_launcher).setTitle(R.string.abt_title).setMessage(String.format(getString(R.string.abt_msg), getString(R.string.app_version)))
                        .setPositiveButton(R.string.btn_upgrade, new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog, int which) {
								new Thread() {
									public void run() {
										handler.sendEmptyMessage(8);
										String ver = Utils.getContent("https://github.com/andersgong/DCTimer2.0/raw/master/release/version.txt");
										if(ver.startsWith("error")) {
											handler.sendEmptyMessage(9);
										} else {
											String[] vers = ver.split("\t");
											int v = 0;
											if (!"".equals(vers[0])) v = Integer.parseInt(vers[0]);
											if(v > version) {
												newVersion = vers[1];
												StringBuilder sb = new StringBuilder(vers[2]);
												if(vers.length > 3)
													for(int i=3; i<vers.length; i++) sb.append("\n"+vers[i]);
												updateCont = sb.toString();
												handler.sendEmptyMessage(16);
											}
											else {
												newVersion = vers[1];
												StringBuilder sb = new StringBuilder(vers[0]);
												for(int i=1; i<vers.length; i++) sb.append("\n"+vers[i]);
												updateCont = sb.toString();
												handler.sendEmptyMessage(33);
											}
										}
									}
								}.start();
							}
						}).setNegativeButton(R.string.btn_close, null).show();
                break;
			case R.id.lay16:	//最慢单次颜色
				colorPickerView = new ColorPickerView(context, dip300, colors[3]);
				new CustomDialog.Builder(context).setTitle(R.string.select_color).setView(colorPickerView).setPositiveButton(R.string.btn_ok, new OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						int color = colorPickerView.getColor();
						colors[3]=color;
						edit.putInt("cl3", color);
						edit.commit();
						updateGridView(0);
					}
				}).setNegativeButton(R.string.btn_cancel, null).show();
				break;
			case R.id.lay17:	//最快平均颜色
				colorPickerView = new ColorPickerView(context, dip300, colors[4]);
				new CustomDialog.Builder(context).setTitle(R.string.select_color).setView(colorPickerView).setPositiveButton(R.string.btn_ok, new OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						int color = colorPickerView.getColor();
						colors[4]=color;
						edit.putInt("cl4", color);
						edit.commit();
						updateGridView(0);
					}
				}).setNegativeButton(R.string.btn_cancel, null).show();
				break;
			case R.id.lay22:	//背景图片
				Intent intent;
				if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) {
					intent = new Intent(Intent.ACTION_GET_CONTENT);
				}
				else {
					intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
				}
                intent.setType("image/*");
				//intent.setAction(Intent.ACTION_GET_CONTENT);
				startActivityForResult(intent, 1);
				break;
			case R.id.lay19:
				//n阶配色设置
				int[] cs = {share.getInt("csn1", Color.YELLOW), share.getInt("csn2", Color.BLUE), share.getInt("csn3", Color.RED),
						share.getInt("csn4", Color.WHITE), share.getInt("csn5", 0xff009900), share.getInt("csn6", 0xffff8026)};
				colorSchemeView = new ColorSchemeView(context, dip300, cs, 1);
				new CustomDialog.Builder(context).setTitle(getString(R.string.scheme_cube)).setView(colorSchemeView)
				.setNegativeButton(R.string.btn_close, null).show();
				break;
			case R.id.lay20:	//金字塔配色
				cs = new int[] {share.getInt("csp1", Color.RED), share.getInt("csp2", 0xff009900),
						share.getInt("csp3", Color.BLUE), share.getInt("csp4", Color.YELLOW)};
				colorSchemeView = new ColorSchemeView(context, dip300, cs, 2);
				new CustomDialog.Builder(context).setTitle(getString(R.string.scheme_pyrm)).setView(colorSchemeView)
				.setNegativeButton(R.string.btn_close, null).show();
				break;
			case R.id.lay21:	//SQ配色
				cs = new int[] {share.getInt("csq1", Color.YELLOW), share.getInt("csq2", Color.BLUE), share.getInt("csq3", Color.RED),
						share.getInt("csq4", Color.WHITE), share.getInt("csq5", 0xff009900), share.getInt("csq6", 0xffff8026)};
				colorSchemeView = new ColorSchemeView(context, dip300, cs, 3);
				new CustomDialog.Builder(context).setTitle(getString(R.string.scheme_sq)).setView(colorSchemeView)
				.setNegativeButton(R.string.btn_close, null).show();
				break;
			case R.id.lay13:	//背景颜色
				colorPickerView = new ColorPickerView(context, dip300, colors[0]);
				new CustomDialog.Builder(context).setTitle(R.string.select_color).setView(colorPickerView).setPositiveButton(R.string.btn_ok, new OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						int color = colorPickerView.getColor();
						changeBackgroudColor(color);
						colors[0] = color;
						useBgcolor = true;
						edit.putInt("cl0", color);
						edit.putBoolean("bgcolor", true);
						edit.commit();
					}
				}).setNegativeButton(R.string.btn_cancel, null).show();
				break;
			case R.id.lay24:	//Skewb配色
				cs = new int[] {share.getInt("csw1", Color.YELLOW), share.getInt("csw2", Color.BLUE), share.getInt("csw3", Color.RED),
						share.getInt("csw4", Color.WHITE), share.getInt("csw5", 0xff009900), share.getInt("csw6", 0xffff8026)};
				colorSchemeView = new ColorSchemeView(context, dip300, cs, 4);
				new CustomDialog.Builder(context).setTitle(getString(R.string.scheme_skewb)).setView(colorSchemeView)
				.setNegativeButton(R.string.btn_close, null).show();
				break;
			case R.id.lay14:	//文字颜色
				colorPickerView = new ColorPickerView(context, dip300, colors[1]);
				new CustomDialog.Builder(context).setTitle(R.string.select_color).setView(colorPickerView).setPositiveButton(R.string.btn_ok, new OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						int color = colorPickerView.getColor();
						colors[1] = color;
						edit.putInt("cl1", color);
						edit.commit();
						setTextsColor();
						setListView();
						setResultTitle();
						updateGridView(0);
					}
				}).setNegativeButton(R.string.btn_cancel, null).show();
				break;
			case R.id.lay15:	//最快单次颜色
				colorPickerView = new ColorPickerView(context, dip300, colors[2]);
				new CustomDialog.Builder(context).setTitle(R.string.select_color).setView(colorPickerView).setPositiveButton(R.string.btn_ok, new OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						int color = colorPickerView.getColor();
						colors[2] = color;
						edit.putInt("cl2", color);
						edit.commit();
						updateGridView(0);
					}
				}).setNegativeButton(R.string.btn_cancel, null).show();
				break;
            case R.id.lay37: //观察倒计时提示音
                LayoutInflater factory2 = LayoutInflater.from(context);
                int layoutId2 = R.layout.number_input;
                view = factory2.inflate(layoutId2, null);
                editText = (EditText) view.findViewById(R.id.edit_text);
                editText.setText(String.valueOf(inspprompt));
                editText.setSelection(editText.getText().length());
                new CustomDialog.Builder(context).setTitle("Input(0~9):").setView(view)
                        .setPositiveButton(R.string.btn_ok, new OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                            	String inp_value = editText.getText().toString();
                                int len = 0;
                                if (!"".equals(inp_value)) len = Integer.parseInt(inp_value);
                                if(len < 0 || len > 9)
                                    Toast.makeText(context, getString(R.string.illegal), Toast.LENGTH_LONG).show();
                                else {
                                    inspprompt = len;
                                    edit.putInt("inspprompt", len);
                                    edit.commit();
                                    stdn[2].setText("" + len);
                                }
                                Utils.hideKeyboard(editText);
                            }
                        }).setNegativeButton(R.string.btn_cancel, new OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        Utils.hideKeyboard(editText);
                    }
                }).show();
                Utils.showKeyboard(editText);
                break;
			case R.id.lay27:
			case R.id.lay28:	//滚动平均长度
				LayoutInflater factory = LayoutInflater.from(context);
				int layoutId = R.layout.number_input;
				view = factory.inflate(layoutId, null);
				editText = (EditText) view.findViewById(R.id.edit_text);
				editText.setText(String.valueOf(sel==R.id.lay27 ? l1len : l2len));
				editText.setSelection(editText.getText().length());
				new CustomDialog.Builder(context).setTitle(R.string.enter_len).setView(view)
				.setPositiveButton(R.string.btn_ok, new OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						String inp_value = editText.getText().toString();
						int len = 0;
						if (!"".equals(inp_value)) len = Integer.parseInt(inp_value);
						if(len < 3 || len > 1000)
							Toast.makeText(context, getString(R.string.illegal), Toast.LENGTH_LONG).show();
						else {
							int idx;
							if(sel == R.id.lay27) {
								idx = 0;
								l1len = len;
								edit.putInt("l1len", len);
								sesAvgNum1.set(sesIdx, len);
								edit.putInt("sesavgnum1" + sesIdx, len);
							} else {
								idx = 1;
								l2len = len;
								edit.putInt("l2len", len);
								sesAvgNum2.set(sesIdx, len);
								edit.putInt("sesavgnum2" + sesIdx, len);
							}
							edit.commit();
							stdn[idx].setText("" + len);
							if(Session.length>0 && !isMulp) {
								setResultTitle();
								updateGridView(1);
							}
						}
						Utils.hideKeyboard(editText);
					}
				}).setNegativeButton(R.string.btn_cancel, new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						Utils.hideKeyboard(editText);
					}
				}).show();
				Utils.showKeyboard(editText);
				break;
				case R.id.lay44:	//手势长度
				case R.id.lay45:	//手势速度
					LayoutInflater factory3 = LayoutInflater.from(context);
					int layoutId3 = R.layout.number_input;
					view = factory3.inflate(layoutId3, null);
					editText = (EditText) view.findViewById(R.id.edit_text);
					editText.setText(String.valueOf(sel==R.id.lay44 ? ges_dist : ges_speed));
					editText.setSelection(editText.getText().length());
					new CustomDialog.Builder(context).setTitle(R.string.enter_len).setView(view)
							.setPositiveButton(R.string.btn_ok, new OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog, int which) {
									String inp_value = editText.getText().toString();
									int len = 0;
									if (!"".equals(inp_value)) len = Integer.parseInt(inp_value);
									if(len < 3 || len > 1000)
										Toast.makeText(context, getString(R.string.illegal), Toast.LENGTH_LONG).show();
									else {
										int idx;
										if(sel == R.id.lay44) {
											idx = 3;
											ges_dist = len;
											edit.putInt("ges_dist", len);
										} else {
											idx = 4;
											ges_speed = len;
											edit.putInt("ges_speed", len);
										}
										edit.commit();
										stdn[idx].setText("" + len);
									}
									Utils.hideKeyboard(editText);
								}
							}).setNegativeButton(R.string.btn_cancel, new OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							Utils.hideKeyboard(editText);
						}
					}).show();
					Utils.showKeyboard(editText);
					break;
				case R.id.lay50: //插入网站
					LayoutInflater factory4 = LayoutInflater.from(context);
					int layoutId4 = R.layout.ses_name;
					view = factory4.inflate(layoutId4, null);
					editText = (EditText) view.findViewById(R.id.edit_ses);
					editText.setText(if_web);
					editText.setSelection(editText.getText().length());
					new CustomDialog.Builder(context).setTitle(R.string.if_tool).setView(view)
							.setPositiveButton(R.string.btn_ok, new OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog, int which) {
									String inp_value = editText.getText().toString();
									if ("".equals(inp_value))
										Toast.makeText(context, getString(R.string.illegal), Toast.LENGTH_LONG).show();
									else {
										if_web = inp_value;
										edit.putString("if_web", if_web);
										edit.commit();
										stdn[5].setText(if_web);
									}
									Utils.hideKeyboard(editText);
								}
							}).setNegativeButton(R.string.btn_cancel, new OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							Utils.hideKeyboard(editText);
						}
					}).show();
					Utils.showKeyboard(editText);
					break;
				case R.id.lay51: //公式网站
				case R.id.lay52:
				case R.id.lay53:
					LayoutInflater factory5 = LayoutInflater.from(context);
					int layoutId5 = R.layout.ses_name;
					int title;
					view = factory5.inflate(layoutId5, null);
					editText = (EditText) view.findViewById(R.id.edit_ses);
					if ( sel == R.id.lay53 ) {
						title = R.string.alg_web3;
						editText.setText(alg_web3);
					}
					else if ( sel == R.id.lay52 ) {
						title = R.string.alg_web2;
						editText.setText(alg_web2);
					}
					else {
						title = R.string.alg_web1;
						editText.setText(alg_web1);
					}
					editText.setSelection(editText.getText().length());
					new CustomDialog.Builder(context).setTitle(title).setView(view)
							.setPositiveButton(R.string.btn_ok, new OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog, int which) {
									String inp_value = editText.getText().toString();
									if ("".equals(inp_value))
										Toast.makeText(context, getString(R.string.illegal), Toast.LENGTH_LONG).show();
									else {
										if ( sel == R.id.lay53 ) {
											alg_web3 = inp_value;
											edit.putString("alg_web3", alg_web3);
											edit.commit();
											stdn[8].setText(alg_web3);
										}
										else if ( sel == R.id.lay52 ) {
											alg_web2 = inp_value;
											edit.putString("alg_web2", alg_web2);
											edit.commit();
											stdn[7].setText(alg_web2);
										}
										else {
											alg_web1 = inp_value;
											edit.putString("alg_web1", alg_web1);
											edit.commit();
											stdn[6].setText(alg_web1);
										}
									}
									Utils.hideKeyboard(editText);
								}
							}).setNegativeButton(R.string.btn_cancel, new OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							Utils.hideKeyboard(editText);
						}
					}).show();
					Utils.showKeyboard(editText);
					break;
			}
		}
	};

	private class gestureListener implements GestureDetector.OnGestureListener{
		// 触发条件 ：
		// X轴的坐标位移大于FLING_MIN_DISTANCE，且移动速度大于FLING_MIN_VELOCITY个像素/秒

		// 用户轻触触摸屏，由1个MotionEvent ACTION_DOWN触发
		public boolean onDown(MotionEvent e) {
			//Log.i("MyGesture", "onDown");
			//Toast.makeText(DCTimer.this, "onDown", Toast.LENGTH_SHORT).show();
			return false;
		}

		/*
         * 用户轻触触摸屏，尚未松开或拖动，由一个1个MotionEvent ACTION_DOWN触发
         * 注意和onDown()的区别，强调的是没有松开或者拖动的状态
         *
         * 而onDown也是由一个MotionEventACTION_DOWN触发的，但是他没有任何限制，
         * 也就是说当用户点击的时候，首先MotionEventACTION_DOWN，onDown就会执行，
         * 如果在按下的瞬间没有松开或者是拖动的时候onShowPress就会执行，如果是按下的时间超过瞬间
         * （这块我也不太清楚瞬间的时间差是多少，一般情况下都会执行onShowPress），拖动了，就不执行onShowPress。
         */
		public void onShowPress(MotionEvent e) {
			//Log.i("MyGesture", "onShowPress");
			//Toast.makeText(DCTimer.this, "onShowPress", Toast.LENGTH_SHORT).show();
		}

		// 用户（轻触触摸屏后）松开，由一个1个MotionEvent ACTION_UP触发
		///轻击一下屏幕，立刻抬起来，才会有这个触发
		//从名子也可以看出,一次单独的轻击抬起操作,当然,如果除了Down以外还有其它操作,那就不再算是Single操作了,所以这个事件 就不再响应
		public boolean onSingleTapUp(MotionEvent e) {
			//Log.i("MyGesture", "onSingleTapUp");
			//Toast.makeText(DCTimer.this, "onSingleTapUp", Toast.LENGTH_SHORT).show();
			return false;
		}

		// 用户按下触摸屏，并拖动，由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
								float distanceX, float distanceY) {
			//Log.i("MyGesture22", "onScroll:"+(e2.getX()-e1.getX()) +"   "+distanceX);
			//Toast.makeText(DCTimer.this, "onScroll", Toast.LENGTH_LONG).show();
			return false;
		}

		// 用户长按触摸屏，由多个MotionEvent ACTION_DOWN触发
		public void onLongPress(MotionEvent e) {
			//Log.i("MyGesture", "onLongPress");
			//Toast.makeText(DCTimer.this, "onLongPress", Toast.LENGTH_LONG).show();
		}

		private boolean my_process(int type)
		{
			switch ( type )
			{
				case 1: //删除最后一次成绩
					if(Session.length==0) {
						Toast.makeText(context, getString(R.string.no_times), Toast.LENGTH_SHORT).show();
					}
					else new CustomDialog.Builder(context).setTitle(R.string.confirm_del_last)
							.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog, int which) {
									session.move(Session.length-1);
									delete(Session.length-1);
								}
							}).setNegativeButton(R.string.btn_cancel, null).show();
					break;

				case 2: //新打乱
					newScramble(crntScrType);
					break;

				case 3: //编辑惩罚
					if(Session.length==0)
					{
						Toast.makeText(context, getString(R.string.no_times), Toast.LENGTH_SHORT).show();
					}
					else {
						showTime(Session.length - 1);
					}
					break;

				case 4: //删除所有成绩
					if(Session.length==0) Toast.makeText(context, getString(R.string.no_times), Toast.LENGTH_SHORT).show();
					else new CustomDialog.Builder(context).setTitle(R.string.confirm_clear_session)
							.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog, int which) {deleteAll();}
							}).setNegativeButton(R.string.btn_cancel, null).show();
					break;

				case 5:
					inputTime(MotionEvent.ACTION_UP);
					break;

				default:
					return false;
			}

			return true;
		}

		// 用户按下触摸屏、快速移动后松开，由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
							   float velocityY) {
			//Log.i("MyGesture", "onFling");
			//Toast.makeText(DCTimer.this, "onFling", Toast.LENGTH_LONG).show();
			if (e1.getX() - e2.getX() > ges_dist
					&& Math.abs(velocityX) > ges_speed) {
				// Fling left
				//Log.i("MyGesture", "Fling left");
				//Toast.makeText(DCTimer.this, "Fling Left", Toast.LENGTH_SHORT).show();
				return my_process(ges_left);
			} else if (e2.getX() - e1.getX() > ges_dist
					&& Math.abs(velocityX) > ges_speed) {
				// Fling right
				//Log.i("MyGesture", "Fling right");
				//Toast.makeText(DCTimer.this, "Fling Right", Toast.LENGTH_SHORT).show();
				return my_process(ges_right);
			}
			else if (e1.getY() - e2.getY() > ges_dist
					&& Math.abs(velocityY) > ges_speed) {
				// Fling up
				//Log.i("MyGesture", "Fling up");
				//Toast.makeText(DCTimer.this, "Fling up", Toast.LENGTH_SHORT).show();
				return my_process(ges_up);
			} else if (e2.getY() - e1.getY() > ges_dist
					&& Math.abs(velocityY) > ges_speed) {
				// Fling down
				//Log.i("MyGesture", "Fling down");
				//Toast.makeText(DCTimer.this, "Fling down", Toast.LENGTH_SHORT).show();
				return my_process(ges_down);
			}

			return false;
		}
	};

	private OnTouchListener mOnTouchListener = new OnTouchListener() {
		@Override
		public boolean onTouch(View v, MotionEvent event) {
			v.performClick();
			switch (v.getId()) {
			case R.id.tv_scr:
				scrTouch = true;
				if (stSel[0] == 2 && stt_inspect && 0 != Timer.state) setTouchSS(event);
				else setTouch(event);
				return Timer.state != 0;
			case R.id.tv_timer:
				//if ( true == mGestureDetector.onTouchEvent(event) ) return true;
				scrTouch = false;
				if(stSel[0] == 0) setTouch(event);
				else if(stSel[0] == 1) inputTime(event.getAction());
				else if (stSel[0] == 2) setTouchSS(event);
				return true;
			}
			return false;
		}
	};
	
	private OnLongClickListener mOnLongClickListener = new OnLongClickListener() {
		@Override
		public boolean onLongClick(View v) {
			if(Timer.state == 0) {
				isLongPress = true;
				LayoutInflater factory = LayoutInflater.from(context);
				int layoutId = R.layout.scr_layout;
				view = factory.inflate(layoutId, null);
				editText = (EditText) view.findViewById(R.id.etslen);
				TextView tvScr = (TextView) view.findViewById(R.id.cnt_scr);
				tvScr.setText(scrambler.crntScr);
				editText.setText(""+Scrambler.scrLen);
				if(Scrambler.scrLen == 0) editText.setEnabled(false);
				else editText.setSelection(editText.getText().length());
				new CustomDialog.Builder(context).setView(view)
				.setPositiveButton(R.string.btn_ok, new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						String text = editText.getText().toString();
						int len = text.equals("") ? 0:Integer.parseInt(text);
						if(editText.isEnabled() && len>0) {
							if(len>180) len = 180;
							if(len != Scrambler.scrLen) {
								Scrambler.scrLen = len;
								if((scrIdx==-1 && scr2idx==17) || (scrIdx==1 && scr2idx==19) || (scrIdx==20 && scr2idx==4))
									scrState = SCRNONE;
								newScramble(crntScrType);
							}
						}
						Utils.hideKeyboard(editText);
					}
				}).setNegativeButton(R.string.copy_scr, new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						if(VERSION.SDK_INT >= 11) {
							android.content.ClipboardManager clip = (android.content.ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
							clip.setPrimaryClip(ClipData.newPlainText("text", scrambler.crntScr));
						}
						else {
							android.text.ClipboardManager clip = (android.text.ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
							clip.setText(scrambler.crntScr);
						}
						Toast.makeText(context, getString(R.string.copy_to_clip), Toast.LENGTH_SHORT).show();
						Utils.hideKeyboard(editText);
					}
				}).show();
			}
			return true;
		}
	};
	
	private OnItemClickListener itemListener = new OnItemClickListener() {
		@Override
		public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
			ListView listView = (ListView) arg0;
			switch (listView.getId()) {
			case R.id.list1:
				int realId = showScrToReal(arg2);
				if(selScr1 != realId - 1) {
					selScr1 = realId - 1;
					scr1Adapter.setSelectItem(selScr1 + 1);
					scr1Adapter.notifyDataSetChanged();
					scr2Adapter.setData(getResources().getStringArray(Utils.get2ndScr(realId-1)));
					if(selScr1 == scrIdx) scr2Adapter.setSelectItem(scr2idx);
					else scr2Adapter.setSelectItem(-1);
					scr2Adapter.notifyDataSetChanged();
				}
				break;
			case R.id.list2:
				if(selScr1 != scrIdx || selScr2 != arg2) {
					scrIdx = selScr1;
					scr2idx = selScr2 = arg2;
					set2ndsel();
				}
				popupWindow.dismiss();
				break;
			default:
				selFilePath = paths.get(arg2);
				tvPathName.setText(selFilePath);
				getFileDirs(selFilePath, false);
			}
		}
	};
	
	private OnSeekBarChangeListener mOnSeekBarChangeListener = new OnSeekBarChangeListener() {
		@Override
		public void onStopTrackingTouch(SeekBar seekBar) {
			switch (seekBar.getId()) {
			case R.id.seekb1:	//计时器字体
				timerSize = seekBar.getProgress() + 50;
				tvSettings[0].setText(String.valueOf(timerSize));
				edit.putInt("ttsize", timerSize);
				tvTimer.setTextSize(timerSize);
				break;
			case R.id.seekb2:	//打乱字体
				scrambleSize = seekBar.getProgress() + 12;
				tvSettings[1].setText(String.valueOf(scrambleSize));
				edit.putInt("stsize", scrambleSize);
				tvScramble.setTextSize(scrambleSize);
				break;
			case R.id.seekb3:	//成绩列表行距
				rowSpacing = seekBar.getProgress() + 20;
				tvSettings[2].setText(String.valueOf(rowSpacing));
				if(Session.length != 0)
					updateGridView(2);
				edit.putInt("intv", rowSpacing);
				break;
			case R.id.seekb4:	//背景图不透明度
				opacity = seekBar.getProgress();
				if(!useBgcolor)
					tabHost.setBackgroundDrawable(Utils.getBackgroundDrawable(context, bitmap, opacity));
				edit.putInt("opac", opacity);
				break;
			case R.id.seekb5:	//启动延时
				freezeTime = seekBar.getProgress();
				tvSettings[3].setText(String.format("%.02fs", freezeTime/20f));
				edit.putInt("tapt", freezeTime);
				break;
			case R.id.seekb6:	//SS参数值
				switchThreshold = seekBar.getProgress();
				tvSettings[2].setText(String.valueOf(switchThreshold));
				edit.putInt("ssvalue", switchThreshold);
				break;
			case R.id.seekb7: 	//打乱状态大小
				sviewSize = seekBar.getProgress() * 10 + 160;
				setScrambleViewSize();
				edit.putInt("svsize", sviewSize);
				break;
			case R.id.seekb10:	//实时平均字体
				realmeanSize = seekBar.getProgress() + 12;
				tvSettings[5].setText(String.valueOf(realmeanSize));
				edit.putInt("realmeansize", realmeanSize);
				tvAvg.setTextSize(realmeanSize);
				break;
			}
			edit.commit();
		}

		@Override
		public void onStartTrackingTouch(SeekBar seekBar) {
			setProgress(seekBar);
		}

		@Override
		public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
			setProgress(seekBar);
		}

		private void setProgress(SeekBar seekBar) {
			int prg = seekBar.getProgress();
			switch (seekBar.getId()) {
			case R.id.seekb1:
				tvSettings[0].setText(String.valueOf(prg+50));
				break;
			case R.id.seekb2:
				tvSettings[1].setText(String.valueOf(prg+12));
				break;
			case R.id.seekb3:
				tvSettings[2].setText(String.valueOf(prg+20));
				break;
			case R.id.seekb5:
				tvSettings[3].setText(String.format("%.02fs", prg / 20f));
				break;
			case R.id.seekb6:
				tvSettings[4].setText(String.valueOf(prg));
				break;
			case R.id.seekb10:	//实时平均字体
				tvSettings[5].setText(String.valueOf(prg+12));
				break;
			}
		}
	};
	
	private View.OnClickListener comboListener = new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			final int sel;
			switch (v.getId()) {
			case R.id.lay01: sel = 0; break;
			case R.id.lay02: sel = 1; break;
			case R.id.lay03: sel = 2; break;
			case R.id.lay04: sel = 3; break;
			case R.id.lay26: sel = 4; break;
			case R.id.lay06: sel = 5; break;
			case R.id.lay07: sel = 6; break;
			case R.id.lay08: sel = 7; break;
			case R.id.lay09: sel = 8; break;
			case R.id.lay10: sel = 9; break;
			case R.id.lay11: sel = 10; break;
			case R.id.lay12: sel = 11; break;
			case R.id.lay23: sel = 12; break;
			case R.id.lay18: sel = 13; break;
			case R.id.lay25: sel = 14; break;
			case R.id.lay30: sel = 15; break;
			case R.id.lay31: sel = 16; break;
			case R.id.lay40: sel = 17; break;
			case R.id.lay41: sel = 18; break;
			case R.id.lay42: sel = 19; break;
			case R.id.lay43: sel = 20; break;
			case R.id.lay46: sel = 21; break;
			case R.id.lay47: sel = 22; break;
			case R.id.lay49: sel = 23; break;
			default: sel = -1; break;
			}
			new CustomDialog.Builder(context).setSingleChoiceItems(staid[sel], stSel[sel], new OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, final int which) {
					if(stSel[sel] != which) {
						switch (sel) {
						case 0:	//计时方式
							if(stSel[0] == 2) stm.stop();
							if (which == 0) setTimerText(stSel[2]==0 ? "0.00" : "0.000");
							else if(which == 1) setTimerText("IMPORT");
							else {
								setTimerText("OFF");
								stm.start();
							}
							edit.putInt("tiway", which);
							break;
						case 1:	//计时器更新方式
							edit.putInt("timerupd", which);
							break;
						case 2:	//计时精确度
							edit.putBoolean("prec", which != 0);
							if(stSel[0] == 0) setTimerText(which==0 ? "0.00" : "0.000");
							if(Session.length != 0) {
								btSesMean.setText(getString(R.string.session_average) + Statistics.sessionMean());
								updateGridView(1);
							}
							break;
						case 3:	//分段计时
							stSel[3] = which;
							if(which == 0) {
								isMulp = false;
								Session.mulp = null;
							} else {
								if(!isMulp) {
									isMulp = true;
									Session.mulp = new int[6][Session.result.length];
									if(Session.length > 0)
										session.getMultData();
								}
							}
							edit.putInt("multp", which);
							setListView();
							setResultTitle();
							break;
						case 4:	//滚动平均2类型
							stSel[4] = which;
							edit.putInt("l2tp", which);
							sesAvgType2.set(sesIdx, which);
							edit.putInt("sesavgtype2" + sesIdx, which);
							if(!isMulp) setResultTitle();
							if(Session.length>0 && !isMulp) {
								setResultTitle();
								updateGridView(1);
							}
							break;
						case 5:	//三阶求解
							edit.putInt("cxe", which);
							if(scrIdx==-1 && (scr2idx==0 || scr2idx==5 || scr2idx==6 || scr2idx==7) ||
									scrIdx==1 && (scr2idx==0 || scr2idx==1 || scr2idx==5 || scr2idx==19)) {
								if(which == 0) tvScramble.setText(scrambler.crntScr);
								else new Thread() {
									public void run() {
										handler.sendEmptyMessage(4);
										scrambler.extSol3(which, scrambler.crntScr);
										extsol = scrambler.sc;
										handler.sendEmptyMessage(3);
										scrState = NEXTSCRING;
										scrambler.extSol3(which, nextScr);
										scrState = SCRDONE;
									}
								}.start();
							}
							break;
						case 6:	//二阶底面
							edit.putInt("cube2l", which);
							if(scrIdx == 0) {
								if(which == 0) tvScramble.setText(scrambler.crntScr);
								else if(scr2idx < 3) new Thread() {
									public void run() {
										handler.sendEmptyMessage(4);
										extsol = "\n"+solver.Cube2bl.cube2layer(scrambler.crntScr, which);
										handler.sendEmptyMessage(3);
										scrState = NEXTSCRING;
										scrambler.sc = "\n"+solver.Cube2bl.cube2layer(nextScr, which);
										scrState = SCRDONE;
									}
								}.start();
							}
							break;
						case 7:	//五魔配色
							edit.putInt("minxc", which);
							break;
						case 8:	//计时器字体
							setTimerFont(which);
							edit.putInt("tfont", which);
							break;
						case 9:	//屏幕方向
							setRequestedOrientation(screenOri[which]);
							edit.putInt("screenori", which);
							break;
						case 10:	//触感反馈
							edit.putInt("vibra", which);
							break;
						case 11:	//触感时间
							edit.putInt("vibtime", which);
							break;
						case 12:	//SQ复形求解
							edit.putInt("sq1s", which);
							if(scrIdx==8 && scr2idx<3) {
								if(which > 0) {
									new Thread() {
										public void run() {
											handler.sendEmptyMessage(4);
											extsol = " " + (which==1 ? Sq1Shape.solveTrn(scrambler.crntScr) : Sq1Shape.solveTws(scrambler.crntScr));
											handler.sendEmptyMessage(1);
											scrState = NEXTSCRING;
											scrambler.sc = " " + (which==1 ? Sq1Shape.solveTrn(nextScr) : Sq1Shape.solveTws(nextScr));
											scrState = SCRDONE;
										}
									}.start();
								}
								else tvScramble.setText(scrambler.crntScr);
							}
							break;
						case 13:	//时间格式
							stSel[13] = which;
							edit.putInt("timeform", which);
							if(Session.length > 0) {
								updateGridView(1);
							}
							break;
						case 14:	//滚动平均1类型
							stSel[14] = which;
							edit.putInt("l1tp", which);
							sesAvgType1.set(sesIdx, which);
							edit.putInt("sesavgtype1" + sesIdx, which);
							if(!isMulp) setResultTitle();
							if(Session.length>0 && !isMulp) {
								setResultTitle();
								updateGridView(1);
							}
							break;
						case 15:	//返回键处理
							stSel[15] = which;
							edit.putInt("backkey", which);
							break;
						case 16:	//实时平均位置
							stSel[16] = which;
							avgLayout = which;
							edit.putInt("avgLayout", which);
							changeRealMeanPos();
							break;
						case 17:	//手势
							ges_left = which;
							edit.putInt("ges_left", which);
							break;
						case 18:	//手势
							ges_right = which;
							edit.putInt("ges_right", which);
							break;
						case 19:	//手势
							ges_up = which;
							edit.putInt("ges_up", which);
							break;
						case 20:	//手势
							ges_down = which;
							edit.putInt("ges_down", which);
							break;
						case 21:	//倒计时提示方式
							stSel[21] = which;
							prompt_time = which;
							edit.putInt("prompt_time", which);
							break;
						case 22:	//手势
							ges_double = which;
							edit.putInt("ges_double", which);
							break;
						case 23:	//语言
							edit.putInt("Language", which);
							break;
						}
						stSel[sel] = which;
						edit.commit();
						std[sel].setText(itemStr[sel][which]);
					}
					dialog.dismiss();
					if ( 23 == sel )
					{
						forceReboot();
					}
				}
			}).setNegativeButton(R.string.btn_close, null).show();
		}
	};
	
	//EG训练打乱
	private CompoundButton.OnCheckedChangeListener mOnCheckedChangeListener = new CompoundButton.OnCheckedChangeListener() {
		@Override
		public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
			switch (buttonView.getId()) {
			case R.id.checkcll:
				if(isChecked) egtype |= 4;
				else egtype &= 3;
				edit.putInt("egtype", egtype);
				break;
			case R.id.checkeg1:
				if(isChecked) egtype |= 2;
				else egtype &= 5;
				edit.putInt("egtype", egtype);
				break;
			case R.id.checkeg2:
				if(isChecked) egtype |= 1;
				else egtype &= 6;
				edit.putInt("egtype", egtype);
				break;
			case R.id.checkegpi:
				if(isChecked) {
					egoll |= 128;
					if(checkBox[10].isChecked()) {checkBox[10].setChecked(false); egoll &= 254;}
				}
				else egoll &= 127;
				edit.putInt("egoll", egoll);
				Utils.setEgOll();
				break;
			case R.id.checkegh:
				if(isChecked) {
					egoll |= 64;
					if(checkBox[10].isChecked()) {checkBox[10].setChecked(false); egoll &= 254;}
				}
				else egoll &= 191;
				edit.putInt("egoll", egoll);
				Utils.setEgOll();
				break;
			case R.id.checkegu:
				if(isChecked) {
					egoll |= 32;
					if(checkBox[10].isChecked()) {checkBox[10].setChecked(false); egoll &= 254;}
				}
				else egoll &= 223;
				edit.putInt("egoll", egoll);
				Utils.setEgOll();
				break;
			case R.id.checkegt:
				if(isChecked) {
					egoll |= 16;
					if(checkBox[10].isChecked()) {checkBox[10].setChecked(false); egoll &= 254;}
				}
				else egoll &= 239;
				edit.putInt("egoll", egoll);
				Utils.setEgOll();
				break;
			case R.id.checkegl:
				if(isChecked) {
					egoll |= 8;
					if(checkBox[10].isChecked()) {checkBox[10].setChecked(false); egoll &= 254;}
				}
				else egoll &= 247;
				edit.putInt("egoll", egoll);
				Utils.setEgOll();
				break;
			case R.id.checkegs:
				if(isChecked) {
					egoll |= 4;
					if(checkBox[10].isChecked()) {checkBox[10].setChecked(false); egoll &= 254;}
				}
				else egoll &= 251;
				edit.putInt("egoll", egoll);
				Utils.setEgOll();
				break;
			case R.id.checkega:
				if(isChecked) {
					egoll |= 2;
					if(checkBox[10].isChecked()) {checkBox[10].setChecked(false); egoll &= 254;}
				}
				else egoll &= 253;
				edit.putInt("egoll", egoll);
				Utils.setEgOll();
				break;
			case R.id.checkegn:
				if(isChecked) {
					egoll |= 1;
					for(int i=3; i<10; i++)
						if(checkBox[i].isChecked()) checkBox[i].setChecked(false);
				}
				else egoll &= 254;
				edit.putInt("egoll", egoll);
				Utils.setEgOll();
				break;
			}
			edit.commit();
		}
	};

	//设置各种View、TextView颜色等 TODO
	private void setViews() {
		//打乱显示
		tvScramble.setTextSize(scrambleSize);
		tvAvg.setTextSize(realmeanSize);
		setScrambleFont(monoscr ? 0 : 1);
		//打乱状态
		setScrambleViewSize();
		//计时器
		tvTimer.setTextSize(timerSize);
		setTimerFont(stSel[8]);
		setTimerColor(colors[1]);
		if(stSel[0] == 0) {
			if(stSel[2] == 0) setTimerText("0.00");
			else setTimerText("0.000");
		} else if(stSel[0] == 1) setTimerText("IMPORT");
		else {
			setTimerText("OFF");
			stm.start();
		}
		//设置选项
		for(int i=0; i<std.length; i++) {
			std[i].setText(itemStr[i][stSel[i]]);
		}
		stdn[0].setText(""+l1len);
		stdn[1].setText(""+l2len);
        stdn[2].setText(""+inspprompt);
		stdn[3].setText(""+ges_dist);
		stdn[4].setText(""+ges_speed);
		stdn[5].setText(if_web);
		stdn[6].setText(alg_web1);
		stdn[7].setText(alg_web2);
		stdn[8].setText(alg_web3);
		btSolver3[0].setText(sol31[solSel[0]]);
		btSolver3[1].setText(sol32[solSel[1]]);
		//屏幕方向
		setRequestedOrientation(screenOri[stSel[9]]);
		//拖动条
		int[] ids = {timerSize - 50, scrambleSize - 12, rowSpacing - 20, opacity, freezeTime, switchThreshold, sviewSize / 10 - 16, realmeanSize - 12};
		for(int i=0; i<ids.length; i++) seekBar[i].setProgress(ids[i]);
		//设置TextView
		tvSettings[0].setText(String.valueOf(timerSize));
		tvSettings[1].setText(String.valueOf(scrambleSize));
		tvSettings[2].setText(String.valueOf(rowSpacing));
		tvSettings[3].setText(String.format("%.02fs", freezeTime/20f));
		tvSettings[4].setText(String.valueOf(switchThreshold));
		tvSettings[5].setText(String.valueOf(realmeanSize));
		//设置开关
		setSwitchOn(ibSwitch[0], wca);
		setSwitchOn(ibSwitch[1], monoscr);
		setSwitchOn(ibSwitch[2], simulateSS);
		setSwitchOn(ibSwitch[3], opnl);
		setSwitchOn(ibSwitch[4], fullScreen);
		setSwitchOn(ibSwitch[5], showscr);
		setSwitchOn(ibSwitch[6], conft);
		setSwitchOn(ibSwitch[7], !hidls);
		setSwitchOn(ibSwitch[8], selScr);
        setSwitchOn(ibSwitch[9], realMean);
		setSwitchOn(ibSwitch[10], stt_inspect);
        setRealMean(realMean);
		//分组平均
		btSesMean.setText(getString(R.string.session_average) + Statistics.sessionMean());
	}
	
	private void setTextsColor() {
		setTimerColor(colors[1]);
		tvScramble.setTextColor(colors[1]);
		tvAvg.setTextColor(colors[1]);
		tvSesName.setTextColor(colors[1]);
		tvTitle.setTextColor(colors[1]);
	}
	
	private void readConf() {	//读取配置 TODO
		Language = share.getInt("Language", 0);
		scrIdx = (byte) share.getInt("sel", 1);	//打乱种类
		DB_TBL_COUNT = share.getInt("sescnt", 15);
		sesItems = new ArrayList(DB_TBL_COUNT);
		sesType = new ArrayList(DB_TBL_COUNT);
		sesnames = new ArrayList(DB_TBL_COUNT);
		sesAvgType1 = new ArrayList(DB_TBL_COUNT);
		sesAvgNum1 = new ArrayList(DB_TBL_COUNT);
		sesAvgType2 = new ArrayList(DB_TBL_COUNT);
		sesAvgNum2 = new ArrayList(DB_TBL_COUNT);
		colors[0] = share.getInt("cl0", 0xff66ccff);	// 背景颜色
		colors[1] = share.getInt("cl1", 0xff000000);	// 文字颜色
		colors[2] = share.getInt("cl2", 0xffff00ff);	//最快单次颜色
		colors[3] = share.getInt("cl3", 0xffff0000);	//最慢单次颜色
		colors[4] = share.getInt("cl4", 0xff009900);	//最快平均颜色
		wca = share.getBoolean("wca", false);	//WCA观察
		stt_inspect = share.getBoolean("stt_inspect", false); //stackmat观察
        realMean = share.getBoolean("realmean", false);	//实时显示平均成绩
		showscr = share.getBoolean("showscr", true);	//显示打乱状态
		monoscr = share.getBoolean("monoscr", false);	//等宽打乱字体
		hidls = share.getBoolean("hidls", false);	//成绩列表隐藏打乱
		conft = share.getBoolean("conft", true);	//提示确认成绩
		solSel[0] = (byte) share.getInt("cface", 0);	// 十字求解底面
		solSel[1] = (byte) share.getInt("cside", 1);	// 三阶求解颜色
		//if(solSel[1] == 6) solSel[1] = 1;
		if_web = share.getString("if_web", "https://fewestmov.es/");
		alg_web1 = share.getString("alg_web1", "http://algdb.net/");
		alg_web2 = share.getString("alg_web2", "https://algs.cuber.pro/");
		alg_web3 = share.getString("alg_web3", null);
		sesIdx = (byte) share.getInt("group", 0);	// 分组
		scr2idx = (byte) share.getInt("sel2", 0);	// 二级打乱
		timerSize = share.getInt("ttsize", 60);	//计时器字体
		scrambleSize = share.getInt("stsize", 18);	//打乱字体
		realmeanSize = share.getInt("realmeansize", 18); //实时平均字体
		stSel[0] = share.getInt("tiway", 0);	// 计时方式
		stSel[1] = share.getInt("timerupd", 0);	// 计时器更新
		stSel[2] = share.getBoolean("prec", true) ? 1 : 0;	// 计时精度
		stSel[3] = share.getInt("multp", 0);	//分段计时
		isMulp = stSel[3] != 0;
		stSel[4] = share.getInt("l2tp", 0);	//滚动平均2类型
		stSel[5] = share.getInt("cxe", 0);	//三阶求解
		stSel[6] = share.getInt("cube2l", 0);	// 二阶底层求解
		stSel[7] = share.getInt("minxc", 1);	//五魔配色
		stSel[8] = share.getInt("tfont", 3);	// 计时器字体
		stSel[9] = share.getInt("screenori", 0);	// 屏幕方向
		stSel[10] = share.getInt("vibra", 0);	// 震动反馈
		stSel[11] = share.getInt("vibtime", 2);	// 震动时长
		stSel[12] = share.getInt("sq1s", 0);	//SQ1复形计算
		stSel[13] = share.getInt("timeform", 0);	//时间格式
		stSel[14] = share.getInt("l1tp", 0);	//滚动平均1类型
		stSel[15] = share.getInt("backkey", 0);
		stSel[16] = share.getInt("avgLayout", 0);
		stSel[17] = share.getInt("ges_left", 1);
		stSel[18] = share.getInt("ges_right", 2);
		stSel[19] = share.getInt("ges_up", 3);
		stSel[20] = share.getInt("ges_down", 4);
		stSel[21] = share.getInt("prompt_time", 2);
		stSel[22] = share.getInt("ges_double", 0);
		stSel[23] = share.getInt("Language", 0);
		ges_left = stSel[17];
		ges_right = stSel[18];
		ges_up = stSel[19];
		ges_down = stSel[20];
		ges_double = stSel[22];
		l1len = share.getInt("l1len", 5);
		l2len = share.getInt("l2len", 12);
		inspprompt = share.getInt("inspprompt", 0);
		useBgcolor = share.getBoolean("bgcolor", true);	//使用背景颜色
		opacity = share.getInt("opac", 35);	//背景图不透明度
		fullScreen = share.getBoolean("fulls", false);	// 全屏显示
		opnl = share.getBoolean("scron", false);	// 屏幕常亮
		selScr = share.getBoolean("selses", true);	//自动选择分组
		picPath = share.getString("picpath", "");	//背景图片路径
		freezeTime = share.getInt("tapt", 0);	//启动延时
		rowSpacing = share.getInt("intv", 30);	//成绩列表行距
		savePath = share.getString("scrpath", defPath);
		for(int i=0; i<DB_TBL_COUNT; i++) {
			sesType.add(share.getInt("sestype" + i, 32));
			sesnames.add(share.getString("sesname" + i, getString(R.string.session) + (i + 1)));

			sesAvgType1.add(share.getInt("sesavgtype1" + i, 0));
			sesAvgNum1.add(share.getInt("sesavgnum1" + i, 5));
			sesAvgType2.add(share.getInt("sesavgtype2" + i, 0));
			sesAvgNum2.add(share.getInt("sesavgnum2" + i, 12));
		}
		egtype = share.getInt("egtype", 7);
		egoll = share.getInt("egoll", 254);
		simulateSS = share.getBoolean("simss", false);
		switchThreshold = share.getInt("ssvalue", 50);
		sviewSize = share.getInt("svsize", 220);
		avgLayout = share.getInt("avgLayout", 0);
		prompt_time = share.getInt("prompt_time", 2);
		if ( sesIdx >= DB_TBL_COUNT )
		{
			sesIdx = 0;
		}
		scrIdx = sesType.get(sesIdx) >> 5;
		scr2idx = sesType.get(sesIdx) & 31;

		if ( sesIdx < sesAvgType1.size() )
		{
			stSel[4] = sesAvgType2.get(sesIdx);
			l1len = sesAvgNum1.get(sesIdx);
			stSel[14] = sesAvgType1.get(sesIdx);
			l2len = sesAvgNum2.get(sesIdx);
		}

		ges_dist = share.getInt("ges_dist", 500);
		ges_speed = share.getInt("ges_speed", 200);
	}
	
	private void removeConf() {
		edit.remove("cl0");	edit.remove("cl1");	edit.remove("cl2");
		edit.remove("cl3");	edit.remove("cl4");	edit.remove("wca");
		edit.remove("cxe"); edit.remove("realmean");
		edit.remove("l1am");	edit.remove("l2am");	edit.remove("mnxc");
		edit.remove("prec");	edit.remove("mulp");	edit.remove("invs");
		edit.remove("tapt");	edit.remove("intv");	edit.remove("opac");
		edit.remove("mclr");	edit.remove("prom");	edit.remove("sq1s");
		edit.remove("l1tp");	edit.remove("l2tp");
		edit.remove("hidls");	edit.remove("conft");	edit.remove("list1");
		edit.remove("list2");	edit.remove("timmh");	edit.remove("tiway");
		edit.remove("cface");	edit.remove("cside");	edit.remove("srate");
		edit.remove("tfont");	edit.remove("vibra");	edit.remove("sqshp");
		edit.remove("fulls");	edit.remove("usess");	edit.remove("scron");
		edit.remove("multp");	edit.remove("minxc");	edit.remove("simss");
		edit.remove("l1len");	edit.remove("l2len");  edit.remove("inspprompt");
		edit.remove("hidscr");	edit.remove("ttsize");	edit.remove("stsize");
		edit.remove("cube2l");	edit.remove("scrgry");	edit.remove("selses");
		edit.remove("ismulp");	edit.remove("svsize"); edit.remove("stt_inspect");
		edit.remove("vibtime");	edit.remove("bgcolor");	edit.remove("ssvalue");
		edit.remove("sensity");	edit.remove("monoscr");	edit.remove("showscr");
		edit.remove("timerupd");	edit.remove("timeform");
		edit.remove("screenori"); edit.remove("backkey"); edit.remove("avgLayout");edit.remove("prompt_time");
		edit.remove("ges_left"); edit.remove("ges_right"); edit.remove("ges_up"); edit.remove("ges_down");
		edit.remove("ges_double"); edit.remove("Language");
		edit.remove("ges_dist"); edit.remove("ges_speed"); edit.remove("if_web"); edit.remove("alg_web1"); edit.remove("alg_web2"); edit.remove("alg_web3");
		edit.commit();
	}
	
	private void setVisibility(boolean v) {	//TODO
		int vi = v ? View.VISIBLE : View.GONE;
		rGroup.setVisibility(vi);
		if ( false == showTabLine ) {
			tabLine.setVisibility(View.GONE);
		} else {
			tabLine.setVisibility(vi);
		}
		btScramble.setVisibility(vi);
		tvTxtSesName.setVisibility(vi);
		tvScramble.setVisibility(vi);
		btOption.setVisibility(vi);
		if ( showscr && v ) {
			scrambleView.setVisibility(vi);
		}
		else {
			scrambleView.setVisibility(View.GONE);
		}
        if(!realMean) tvAvg.setVisibility(View.GONE);
		else tvAvg.setVisibility(vi);
		if(!fullScreen) {
			setFullScreen(!v);
		}
	}

    private void setTimerAvg() {
        currentMean();
    }

	private void set2ndsel() {
		if(scrIdx < -1 || scrIdx > 21) scrIdx = 1;
		scr2Ary = getResources().getStringArray(Utils.get2ndScr(scrIdx));
		if(scr2idx >= scr2Ary.length || scr2idx < 0) scr2idx = 0;
		btScramble.setText(scrAry[scrIdx+1] + " - " + scr2Ary[scr2idx]);
		//System.out.println("================" + scrIdx + "===" + scr2idx + "===" + (scrIdx << 5 | scr2idx));
		newScramble(scrIdx << 5 | scr2idx);
	}

    private void newScramble(final int scrType) {
		final boolean ch = crntScrType != scrType;
		crntScrType = scrType;
		if(!ch && inScr!=null && inScrLen<inScr.size()) {
			if(!isInScr) isInScr = true;
			scrambler.crntScr = inScr.get(inScrLen++);
			scrambler.viewType = Utils.getViewType(scrambler.crntScr);
			switch (Configs.insType) {
			case 1:
				if(scrambler.viewType != 2) scrambler.viewType = 0;
				break;
			case 2:
				if(scrambler.viewType != 3) scrambler.viewType = 3;
				break;
			case 3:
				if(scrambler.viewType != 4) scrambler.viewType = 0;
				break;
			case 4:
				if(scrambler.viewType != 5) scrambler.viewType = 0;
				break;
			case 5:
				if(scrambler.viewType != Scrambler.TYPE_PYR) scrambler.viewType = 0;
			case 6:
				if(scrambler.viewType != Scrambler.TYPE_SKW) scrambler.viewType = 0;
			}
			if(scrambler.viewType==3 && stSel[5]!=0) {
				new Thread() {
					public void run() {
						handler.sendEmptyMessage(4);
						scrambler.extSol3(stSel[5], scrambler.crntScr);
						extsol = scrambler.sc;
						handler.sendEmptyMessage(3);
						showScrambleView(true);
					}
				}.start();
			} else {
				tvScramble.setText(scrambler.crntScr);
				showScrambleView(false);
			}
			
		} else if((scrIdx==-1 && (scr2idx<2 || (scr2idx>3 && scr2idx<8) || scr2idx==10 || scr2idx==15 || scr2idx==17)) ||
				(scrIdx==0 && scr2idx<3 && stSel[6]!=0) ||
				(scrIdx==1 && (scr2idx!=0 || (stSel[5]!=0 && (scr2idx<2 || scr2idx==5 || scr2idx==19)))) ||
				(scrIdx==8 && (scr2idx>1 || (scr2idx<3 && stSel[12]>0))) ||
				(scrIdx==11 && scr2idx>3 && scr2idx<7) ||
				(scrIdx==17 && (scr2idx<3 || scr2idx==6)) ||
				scrIdx==20) {	//TODO
			if(isInScr) isInScr = false;
			if(ch) scrState = SCRNONE;
			if(scrState == SCRNONE || scrState == SCRDONE) {
				new Thread() {
					public void run() {
						if(scrState == SCRDONE) {
							scrambler.crntScr = nextScr;
							extsol = scrambler.sc;
						} else {
							scrState = SCRING;
							if(scrIdx==-1 && (scr2idx==1 || scr2idx == 15)) {
								cs.threephase.Util.init(handler);
							}
							handler.sendEmptyMessage(2);
							scrambler.crntScr = scrambler.getScramble((scrIdx<<5)|scr2idx, ch);
							extsol = scrambler.sc;
						}
						if(scrType == crntScrType) {
							showScramble();
							scrState = NEXTSCRING;
							getNextScramble(ch);
						}
					}
				}.start();
			} else if(scrState == NEXTSCRING) {
				if(!nextScrWaiting) {
					nextScrWaiting = true;
					tvScramble.setText(getString(R.string.scrambling));
				}
			}
		} else {
			scrState = SCRING;
			scrambler.crntScr = scrambler.getScramble(scrIdx<<5|scr2idx, ch);
			tvScramble.setText(scrambler.crntScr);
			showScrambleView(false);
			scrState = SCRDONE;
		}
	}
	
	private void showScramble() {
		if((scrIdx==0 && stSel[6]!=0) ||
				(stSel[5]!=0 && (scrIdx==-1 && (scr2idx==0 || scr2idx==5 || scr2idx==6 || scr2idx==7) ||
						scrIdx==1 && (scr2idx==0 || scr2idx==1 || scr2idx==5 || scr2idx==19))))
			handler.sendEmptyMessage(3);
		else if(scrIdx==8 && scr2idx<3 && stSel[12]>0)
			handler.sendEmptyMessage(1);
		else handler.sendEmptyMessage(0);
		showScrambleView(true);
	}
	
	private void showScrambleView(boolean isThread) {
		if (!showscr) return;
		//if(bmScrView != null) bmScrView.recycle();
		if(scrambler.viewType > 0) {
			bmScrView = Bitmap.createBitmap(dip300, dip300*3/4, Config.ARGB_8888);
			Canvas c = new Canvas(bmScrView);
			c.drawColor(0);
			Paint p = new Paint();
			p.setAntiAlias(true);
			scrambler.drawScr(scr2idx, dip300, p, c);
			if(isThread) handler.sendEmptyMessage(15);
			else {
				scrambleView.setVisibility(View.VISIBLE);
				scrambleView.setImageBitmap(bmScrView);
			}
		} else if(isThread) handler.sendEmptyMessage(14);
		else scrambleView.setVisibility(View.GONE);
	}
	
	private void getNextScramble(boolean ch) {
		//System.out.println("get next scramble...");
		scrState = NEXTSCRING;
		nextScr = scrambler.getScramble((scrIdx<<5)|scr2idx, ch);
		//System.out.println("next scr: " + nextScr);
		//System.out.println("next solve: " + Scramble.sc);
		scrState = SCRDONE;
		if(nextScrWaiting) {
			scrambler.crntScr = nextScr;
			extsol = scrambler.sc;
			showScramble();
			nextScrWaiting = false;
			getNextScramble(ch);
		}
	}
	
	private void changeScramble(int s1, int s2) {
		boolean changed = false;
		if(scrIdx != s1) {
			changed = true;
			scrIdx = s1;
		}
		if(scr2idx != s2) {
			changed = true;
			scr2idx = s2;
		}
		if(changed) {
			set2ndsel();
			if(inScr != null && inScr.size() != 0) inScr = null;
		}
	}
	
	private void setScrambleFont(int font) {
		if (font == 0) {
			tvScramble.setTypeface(Typeface.create("monospace", 0));
			tvAvg.setTypeface(Typeface.create("monospace", 0));
		}
		else
		{
			tvScramble.setTypeface(Typeface.create("sans-serif", 0));
			tvAvg.setTypeface(Typeface.create("sans-serif", 0));
		}
	}
	
	private void setScrambleViewSize() {
		LayoutParams params = new LayoutParams((int)(sviewSize*scale), (int)(sviewSize*3*scale)/4);
		params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
		params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
		scrambleView.setLayoutParams(params);
	}
	
	private void setTimerFont(int font) {
		switch (font) {
		case 0: tvTimer.setTypeface(Typeface.create("monospace", 0)); break;
		case 1: tvTimer.setTypeface(Typeface.create("serif", 0)); break;
		case 2: tvTimer.setTypeface(Typeface.create("sans-serif", 0)); break;
		case 3: tvTimer.setTypeface(Typeface.createFromAsset(getAssets(), "Ds.ttf")); break;
		case 4: tvTimer.setTypeface(Typeface.createFromAsset(getAssets(), "Df.ttf")); break;
		case 5: tvTimer.setTypeface(Typeface.createFromAsset(getAssets(), "lcd.ttf")); break;
		}
	}
	
	public void setTimerText(String str) {
		tvTimer.setText(str);
	}

	public void setTimerSound(int sec)
    {
		if ( 2 == prompt_time )
		{
			if ( sec != promptSec && (8 == sec || 12 == sec) ) {
				promptSec = sec;
				//Log.d("DCTimer", "=====================play " + (15 - sec));
				soundPool.play(15 - sec, 1, 1, 1, 0, 1);
			}
		}
        else if ( sec != promptSec && 0 < inspprompt && inspprompt < 15 && 15 > sec && (15 - inspprompt) <= sec )
        {
            promptSec = sec;
            if ( 0 == prompt_time || (15 - inspprompt) == sec ) {
				//Log.d("DCTimer", "=====================play " + (15 - sec));
				soundPool.play(15 - sec, 1, 1, 1, 0, 1);
			}
        }
    }
	
	public void setTimerColor(int color) {
		tvTimer.setTextColor(color);
	}
	
	private void setTouch(MotionEvent e) {
		if(!simulateSS || scrTouch) {
			switch (e.getActionMasked()) {
				case MotionEvent.ACTION_DOWN:
					touchDown(e);
					break;
				case MotionEvent.ACTION_POINTER_DOWN:
					touchDoubleDown(e);
					break;
				case MotionEvent.ACTION_UP:
					touchUp(e);
					break;
				case MotionEvent.ACTION_CANCEL:
					timer.stopFreeze();
					setTimerColor(colors[1]);
					break;
			}
		} else {
			int count = e.getPointerCount();
			//System.out.println(count+", "+e.getAction());
			switch (e.getAction()) {
				case MotionEvent.ACTION_DOWN:
				case MotionEvent.ACTION_MOVE:
				case MotionEvent.ACTION_POINTER_DOWN:
				case 261:
					//System.out.println(e.getX()+", "+e.getY());
					if(count > 1) {
						int x1 = (int)e.getX(0)*2/tvTimer.getWidth();
						int x2 = (int)e.getX(1)*2/tvTimer.getWidth();
						if((x1 ^ x2) == 1) {
							if(!touchDown) {
								touchDown(e);
								touchDown = true;
							}
						}
					}
					break;
				case MotionEvent.ACTION_UP:
				case MotionEvent.ACTION_POINTER_UP:
				case 262:
					if(touchDown) {
						touchDown = false;
						touchUp(e);
					}
					break;
				case MotionEvent.ACTION_CANCEL:
					timer.stopFreeze();
					setTimerColor(colors[1]);
					break;
			}
		}
	}

	private void setTouchSS(MotionEvent e) {
		if ( !scrTouch ) {
			switch (e.getActionMasked()) {
				case MotionEvent.ACTION_UP:
					touchUpSS(e);
					break;
			}
		}
	}

	private void touchDown(MotionEvent event) {
		if(Timer.state == 1) {
			if(mulpCount != 0) {
				if(stSel[10]==1 || stSel[10]==3)
					vibrator.vibrate(vibTime[stSel[11]]);
				setTimerColor(0xff00ff00);
				Session.multemp[stSel[3]+1-mulpCount] = System.currentTimeMillis();
			} else {
				timer.timeEnd = System.currentTimeMillis();
				if (stSel[10] > 1)
					vibrator.vibrate(vibTime[stSel[11]]);
				if ( 6 == ges_double )
				{
					Timer.state = 100; //暂停
				}
				else {
					timer.count();
					if (isMulp) Session.multemp[stSel[3] + 1] = timer.timeEnd;
					setVisibility(true);
				}
			}
		}
		else if(Timer.state != 3 && Timer.state < 100) {
			if(!scrTouch || Timer.state==2) {
				if(freezeTime == 0 || (wca && Timer.state==0)) {
					setTimerColor(0xff00ff00);
					canStart = true;
				} else {
					if(Timer.state==0) setTimerColor(0xffff0000);
					else setTimerColor(0xffffff00);
					timer.startFreeze();
				}
			}
		}
	}

	private void touchDoubleDown(MotionEvent event) {
		if ( 6 != ges_double ) return;
		if ( 100 == Timer.state )
		{
			Timer.state = 101; //暂停
			setTimerText(Statistics.timeToString((int)(timer.timeEnd - timer.timeStart)) + "\n" + getString(R.string.pause));
			Toast toast = Toast.makeText(context, getString(R.string.pause_op), Toast.LENGTH_SHORT);
			toast.setGravity(Gravity.CENTER, 0, 0);
			toast.show();
		}
		else if ( 101 == Timer.state )
		{
			Timer.state = 102;
		}
	}

	private void touchUp(MotionEvent event) {
		if(Timer.state == 0) {
			if(isLongPress) isLongPress = false;
			else if(scrTouch) newScramble(crntScrType);
			else {
				if(freezeTime ==0 || canStart) {
					timer.timeStart = System.currentTimeMillis();
					if(stSel[10]==1 || stSel[10]==3)
						vibrator.vibrate(vibTime[stSel[11]]);
					timer.count();
					if(isMulp) {
						mulpCount = stSel[3];
						Session.multemp[0] = timer.timeStart;
					}
					else mulpCount = 0;
					acquireWakeLock();
					setVisibility(false);
				} else {
					timer.stopFreeze();
					setTimerColor(colors[1]);
				}
			}
		} else if(Timer.state == 1) {
			if(isLongPress) isLongPress = false;
			if(mulpCount!=0) {
				mulpCount--;
				setTimerColor(colors[1]);
			}
		}
		else if(Timer.state == 2) {
			if(isLongPress) isLongPress = false;
			if(freezeTime ==0 || canStart) {
				timer.timeStart = System.currentTimeMillis();
				isp2 = timer.insp==2 ? 2000 : 0;
				idnf = timer.insp != 3;
				if(stSel[10]==1 || stSel[10]==3)
					vibrator.vibrate(vibTime[stSel[11]]);
				timer.count();
				if(isMulp) Session.multemp[0] = timer.timeStart;
				acquireWakeLock();
				setVisibility(false);
			} else {
				timer.stopFreeze();
				setTimerColor(0xffff0000);
			}
		}
		else if ( 101 == Timer.state )
		{}
		else if ( 102 == Timer.state )
		{
			timer.timeStart += (System.currentTimeMillis() - timer.timeEnd);
			timer.timeEnd += (System.currentTimeMillis() - timer.timeEnd);
			Timer.state = 1;
		}
		else if ( 100 >= Timer.state ) {
			if (Timer.state == 100)
			{
				Timer.state = 1;
				timer.count();
				if (isMulp) Session.multemp[stSel[3] + 1] = timer.timeEnd;
				setVisibility(true);
			}
			if(isLongPress) isLongPress = false;
			if(!wca) {isp2=0; idnf=true;}
			confirmTime((int)timer.time);
			Timer.state = 0;
			if(!opnl) releaseWakeLock();
		}
	}

	private void touchUpSS(MotionEvent event) {
		//Toast.makeText(context, "" + Timer.state + " " + Configs.wca + " " + stm.ss_state, Toast.LENGTH_SHORT).show();
		if(Timer.state != 0 || !Configs.wca || stm.ss_state != 5 || !stt_inspect) return;
		if (Timer.state==2 && scrTouch) return;

		timer.timeStart = System.currentTimeMillis();
		if(stSel[10]==1 || stSel[10]==3)
			vibrator.vibrate(vibTime[stSel[11]]);
		timer.count();
	}
	
	private void inputTime(int action) {
		switch (action) {
		case MotionEvent.ACTION_DOWN:
			setTimerColor(0xff00ff00);
			break;
		case MotionEvent.ACTION_UP:
			setTimerColor(colors[1]);
			LayoutInflater factory = LayoutInflater.from(context);
			int layoutId = R.layout.editbox_layout;
			view = factory.inflate(layoutId, null);
			editText = (EditText) view.findViewById(R.id.edit_text);
			new CustomDialog.Builder(context).setTitle(R.string.enter_time).setView(view)
			.setPositiveButton(R.string.btn_ok, new OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					String time = Utils.convertStr(editText.getText().toString());
					if(time.equals("Error") || Utils.parseTime(time)==0)
						Toast.makeText(context, getString(R.string.illegal), Toast.LENGTH_SHORT).show();
					else save(Utils.parseTime(time), (byte) 0);
					Utils.hideKeyboard(editText);
				}
			}).setNegativeButton(R.string.btn_cancel, new OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					Utils.hideKeyboard(editText);
				}
			}).show();
			Utils.showKeyboard(editText);
			break;
		}
	}
	
	public void confirmTime(final int time) {
		if(idnf) {
			if(conft) {
				new CustomDialog.Builder(context).setTitle(getString(R.string.show_time)+Statistics.timeToString(time + isp2))
						.setItems(R.array.rstcon, new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						switch (which) {
						case 0: if (0 < isp2) save(time, 1); else save(time + isp2, 0);break;
						case 1:save(time + isp2, 1);break;
						case 2:save(time + isp2, 2);break;
						}
					}
				}).setNegativeButton(R.string.btn_cancel, new OnClickListener() {
					public void onClick(DialogInterface d,int which) {
						newScramble(crntScrType);
					}
				}).show();
			} else save(time + isp2, 0);
		} else if(conft)
			new CustomDialog.Builder(context).setTitle(getString(R.string.show_time)+"DNF("+Statistics.timeToString(time)+")").setMessage(R.string.confirm_adddnf)
			.setPositiveButton(R.string.btn_ok, new OnClickListener() {
				public void onClick(DialogInterface dialoginterface, int j) {
					save(time, 2);
				}
			}).setNegativeButton(R.string.btn_cancel, new OnClickListener() {
				public void onClick(DialogInterface d,int which) {
					newScramble(crntScrType);
				}
			}).show();
		else save(time, 2);
	}
	
	private void save(int time, int p) {
		session.insert(time, p, scrambler.crntScr, isMulp);
		btSesMean.setText(getString(R.string.session_average) + Statistics.sessionMean());
		updateGridView(3);
		if(sesType.get(sesIdx) != crntScrType) {
			sesType.set(sesIdx, crntScrType);
			edit.putInt("sestype"+sesIdx, crntScrType);
			edit.commit();
		}
		newScramble(crntScrType);
	}
	
	private void getSession(int i) {
		session.getSession(i, isMulp);
	}
	
	private void setResultTitle() {
		layoutTitle.removeAllViews();
		TextView tvNum = new TextView(context);
		tvNum.setLayoutParams(new LinearLayout.LayoutParams((int) Math.round(scale * 50), -1));
		layoutTitle.addView(tvNum);
		String[] title;
		if(isMulp) {
			title = new String[stSel[3] + 2];
			title[0] = getString(R.string.time);
			for(int i=1; i<stSel[3]+2; i++) title[i] = "P-" + i;
		} else {
			title = new String[] {getString(R.string.time),
					(stSel[14]==0 ? "avg of " : "mean of ") + l1len,
					(stSel[4]==0 ? "avg of " : "mean of ") + l2len};
		}
		for(int i=0; i<title.length; i++) {
			//View v = new View(context);
			//v.setLayoutParams(new LinearLayout.LayoutParams(1, -1));
			//v.setBackgroundColor(0xddb2b2b2);
			//layoutTitle.addView(v);
			TextView tv = new TextView(context);
			tv.setLayoutParams(new LinearLayout.LayoutParams(0, -1, 1));
			tv.setTextColor(0xff000000);
			tv.setGravity(Gravity.CENTER);
			tv.setText(title[i]);
			tv.setTextSize(16);
			layoutTitle.addView(tv);
		}
	}
	
	private void setListView() {	//TODO
		if(!isMulp) {
			timeAdapter = new ListAdapter(this, (int) Math.round(rowSpacing * scale));
		} else {
			timeAdapter = new ListAdapter(this, (int) Math.round(rowSpacing * scale), stSel[3]+3);
		}
		lvTimes.setAdapter(timeAdapter);
	}
	
	private void exportDB(final String path) {
		File f = new File(defPath);
		if(!f.exists()) f.mkdirs();
		progressDialog.setTitle(getString(R.string.out_db));
		progressDialog.setMax(DB_TBL_COUNT);
		progressDialog.show();
		new Thread() {
			public void run() {
				try {
					BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path), "UTF-8"));
					for(int i=0; i<DB_TBL_COUNT; i++) {
						handler.sendEmptyMessage(100 + i);
						Cursor cur = session.getCursor(i);
						int count = cur.getCount();
						if(count == 0) continue;
						writer.write(i+1+"::"+sesnames.get(i)+"::"+sesType.get(i)+"::"+sesAvgType1.get(i)+"::"+sesAvgNum1.get(i)+"::"+sesAvgType2.get(i)+"::"+sesAvgNum2.get(i)+"\r\n");
						cur.moveToFirst();
						for(int j=0; j<count; j++) {
							writer.write(cur.getInt(1)+"\t"+cur.getInt(2)+"\t"+cur.getInt(3)+"\t");
							writer.write(cur.getString(4).replace("\n", "\\n")+"\t"+cur.getString(5)+"\t");
							if(cur.getString(6) != null)
								writer.write(cur.getString(6).replace("\t", "\\t")+"\t");
							else writer.write("\t");
							writer.write(cur.getInt(7)+"\t"+cur.getInt(8)+"\t"+cur.getInt(9)+"\t"
									+cur.getInt(10)+"\t"+cur.getInt(11)+"\t"+cur.getInt(12)+"\r\n");
							cur.moveToNext();
						}
						cur.close();
					}
					writer.close();
					handler.sendEmptyMessage(7);
				} catch (Exception e) {
					e.printStackTrace();
					handler.sendEmptyMessage(5);
				}
				progressDialog.dismiss();
			}
		}.start();
	}

	private void importDB(final String path) {
		progressDialog.setTitle(getString(R.string.in_db));
		progressDialog.setMax(DB_TBL_COUNT);
		progressDialog.show();
		new Thread() {
			public void run() {
				int dbCount = 0;
				try {
					BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(path), "UTF-8"));
					String line = "";
					int count = 1;
					DBHelper dbh = new DBHelper(context);
					SQLiteDatabase db = dbh.getWritableDatabase();
					db.beginTransaction();
					SQLiteStatement stmt = null;// = db.compileStatement("insert into commodity(commodity_icon, commodity_photo, category_id, commodity_name, commodity_price) values(?, ?, ?, ?, ?)");

					while (((line = reader.readLine()) != null)) {
						if(!line.contains("\t")) {
							if (!line.contains("::")) {
								crntProgress = Integer.parseInt(line);
								dbh.create_tbl(crntProgress);
								Cursor cur = db.query(DBHelper.TBL_NAME.get(crntProgress - 1).toString(), null, null, null, null, null, null);
								if (cur.getCount() > 0) {
									cur.moveToLast();
									count = cur.getInt(0) + 1;
								} else count = 1;
								cur.close();
								stmt = db.compileStatement("insert into " + DBHelper.TBL_NAME.get(crntProgress - 1).toString() + " values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
								handler.sendEmptyMessage(100 + crntProgress);
							}
							else {
								String[] ts = line.split("::");
								crntProgress = Integer.parseInt(ts[0]);
								dbh.create_tbl(crntProgress);
								edit.putString("sesname" + (crntProgress - 1), ts[1]);
								edit.putInt("sestype" + (crntProgress - 1), Integer.parseInt(ts[2]));
								edit.putInt("sesavgtype1" + (crntProgress - 1), Integer.parseInt(ts[3]));
								edit.putInt("sesavgnum1" + (crntProgress - 1), Integer.parseInt(ts[4]));
								edit.putInt("sesavgtype2" + (crntProgress - 1), Integer.parseInt(ts[5]));
								edit.putInt("sesavgnum2" + (crntProgress - 1), Integer.parseInt(ts[6]));
								Cursor cur = db.query(DBHelper.TBL_NAME.get(crntProgress - 1).toString(), null, null, null, null, null, null);
								if (cur.getCount() > 0) {
									cur.moveToLast();
									count = cur.getInt(0) + 1;
								} else count = 1;
								cur.close();
								stmt = db.compileStatement("insert into " + DBHelper.TBL_NAME.get(crntProgress - 1).toString() + " values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
								handler.sendEmptyMessage(100 + crntProgress);
							}
						} else {
							String[] ts = line.split("\t");
							stmt.bindLong(1, count++);
							stmt.bindLong(2, Integer.parseInt(ts[0]));
							stmt.bindLong(3, Integer.parseInt(ts[1]));
							stmt.bindLong(4, Integer.parseInt(ts[2]));
							stmt.bindString(5, ts[3].replace("\\n", "\n"));
							if(ts[4].equals("null")) stmt.bindString(6, "");
							else stmt.bindString(6, ts[4]);
							if(ts[5].equals("null")) stmt.bindString(7, "");
							else stmt.bindString(7, ts[5].replace("\\t", "\t"));
							for(int i=0; i<6; i++)
								stmt.bindLong(i+8, Integer.parseInt(ts[i+6]));
							stmt.execute();
							stmt.clearBindings();
							dbCount++;
						}
					}
					db.setTransactionSuccessful();
					db.endTransaction();
					reader.close();
					DB_TBL_COUNT = dbh.getTblCount();
					edit.putInt("sescnt", DB_TBL_COUNT);
					progressDialog.dismiss();
					handler.sendEmptyMessage(12);
					if(dbCount > 0) {
						getSession(sesIdx);
						handler.sendEmptyMessage(13);
					}
				} catch (Exception e) {
					progressDialog.dismiss();
					handler.sendEmptyMessage(11);
				}
			}
		}.start();
	}

	private void exportSettings(final String path) {
		File f = new File(defPath);
		if(!f.exists()) f.mkdirs();

		try {
			BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path), "UTF-8"));

			writer.write("sel::0::"+share.getInt("sel", 1)+"\r\n");
			writer.write("sescnt::0::"+share.getInt("sescnt", 15)+"\r\n");
			writer.write("cl0::0::"+share.getInt("cl0", 0xff66ccff)+"\r\n");
			writer.write("cl1::0::"+share.getInt("cl1", 0xff000000)+"\r\n");
			writer.write("cl2::0::"+share.getInt("cl2", 0xffff00ff)+"\r\n");
			writer.write("cl3::0::"+share.getInt("cl3", 0xffff0000)+"\r\n");
			writer.write("cl4::0::"+share.getInt("cl4", 0xff009900)+"\r\n");
			writer.write("wca::1::"+share.getBoolean("wca", false)+"\r\n");
			writer.write("stt_inspect::1::"+share.getBoolean("stt_inspect", false)+"\r\n");
			writer.write("realmean::1::"+share.getBoolean("realmean", false)+"\r\n");
			writer.write("showscr::1::"+share.getBoolean("showscr", true)+"\r\n");
			writer.write("monoscr::1::"+share.getBoolean("monoscr", false)+"\r\n");
			writer.write("hidls::1::"+share.getBoolean("hidls", false)+"\r\n");
			writer.write("conft::1::"+share.getBoolean("conft", true)+"\r\n");
			writer.write("cface::0::"+(byte) share.getInt("cface", 0)+"\r\n");
			writer.write("cside::0::"+(byte) share.getInt("cside", 1)+"\r\n");
			writer.write("group::0::"+(byte) share.getInt("group", 0)+"\r\n");
			writer.write("sel2::0::"+(byte) share.getInt("sel2", 0)+"\r\n");
			writer.write("ttsize::0::"+share.getInt("ttsize", 60)+"\r\n");
			writer.write("stsize::0::"+share.getInt("stsize", 18)+"\r\n");
			writer.write("realmeansize::0::"+share.getInt("realmeansize", 18)+"\r\n");
			writer.write("tiway::0::"+share.getInt("tiway", 0)+"\r\n");
			writer.write("timerupd::0::"+share.getInt("timerupd", 0)+"\r\n");
			writer.write("prec::1::"+share.getBoolean("prec", true)+"\r\n");
			writer.write("multp::0::"+share.getInt("multp", 0)+"\r\n");
			writer.write("l2tp::0::"+share.getInt("l2tp", 0)+"\r\n");
			writer.write("cxe::0::"+share.getInt("cxe", 0)+"\r\n");
			writer.write("cube2l::0::"+share.getInt("cube2l", 0)+"\r\n");
			writer.write("minxc::0::"+share.getInt("minxc", 1)+"\r\n");
			writer.write("tfont::0::"+share.getInt("tfont", 3)+"\r\n");
			writer.write("screenori::0::"+share.getInt("screenori", 0)+"\r\n");
			writer.write("vibra::0::"+share.getInt("vibra", 0)+"\r\n");
			writer.write("vibtime::0::"+share.getInt("vibtime", 2)+"\r\n");
			writer.write("sq1s::0::"+share.getInt("sq1s", 0)+"\r\n");
			writer.write("timeform::0::"+share.getInt("timeform", 0)+"\r\n");
			writer.write("l1tp::0::"+share.getInt("l1tp", 0)+"\r\n");
			writer.write("backkey::0::"+share.getInt("backkey", 0)+"\r\n");
			writer.write("avgLayout::0::"+share.getInt("avgLayout", 0)+"\r\n");
			writer.write("ges_left::0::"+share.getInt("ges_left", 1)+"\r\n");
			writer.write("ges_right::0::"+share.getInt("ges_right", 2)+"\r\n");
			writer.write("ges_up::0::"+share.getInt("ges_up", 3)+"\r\n");
			writer.write("ges_down::0::"+share.getInt("ges_down", 4)+"\r\n");
			writer.write("prompt_time::0::"+share.getInt("prompt_time", 2)+"\r\n");
			writer.write("ges_double::0::"+share.getInt("ges_double", 0)+"\r\n");
			writer.write("l1len::0::"+share.getInt("l1len", 5)+"\r\n");
			writer.write("l2len::0::"+share.getInt("l2len", 12)+"\r\n");
			writer.write("inspprompt::0::"+share.getInt("inspprompt", 0)+"\r\n");
			writer.write("bgcolor::1::"+share.getBoolean("bgcolor", true)+"\r\n");
			writer.write("opac::0::"+share.getInt("opac", 35)+"\r\n");
			writer.write("fulls::1::"+share.getBoolean("fulls", false)+"\r\n");
			writer.write("scron::1::"+share.getBoolean("scron", false)+"\r\n");
			writer.write("selses::1::"+share.getBoolean("selses", true)+"\r\n");
			writer.write("picpath::2::"+share.getString("picpath", "")+"\r\n");
			writer.write("tapt::0::"+share.getInt("tapt", 0)+"\r\n");
			writer.write("intv::0::"+share.getInt("intv", 30)+"\r\n");
			writer.write("scrpath::2::"+share.getString("scrpath", defPath)+"\r\n");
			//for(int i=0; i<DB_TBL_COUNT; i++) {
			//	writer.write("sestype" + i + "::"+share.getInt("sestype" + i, 32)+"\r\n");
			//	writer.write("sesname" + i + "::"+share.getString("sesname" + i, getString(R.string.session) + (i + 1))+"\r\n");
			//	writer.write("sesavgtype1" + i + "::"+share.getInt("sesavgtype1" + i, 0)+"\r\n");
			//	writer.write("sesavgnum1" + i + "::"+share.getInt("sesavgnum1" + i, 5)+"\r\n");
			//	writer.write("sesavgtype2" + i + "::"+share.getInt("sesavgtype2" + i, 0)+"\r\n");
			//	writer.write("sesavgnum2" + i + "::"+share.getInt("sesavgnum2" + i, 12)+"\r\n");
			//}
			writer.write("egtype::0::"+share.getInt("egtype", 7)+"\r\n");
			writer.write("egoll::0::"+share.getInt("egoll", 254)+"\r\n");
			writer.write("simss::1::"+share.getBoolean("simss", false)+"\r\n");
			writer.write("ssvalue::0::"+share.getInt("ssvalue", 50)+"\r\n");
			writer.write("svsize::0::"+share.getInt("svsize", 220)+"\r\n");
			writer.write("avgLayout::0::"+share.getInt("avgLayout", 0)+"\r\n");
			writer.write("prompt_time::0::"+share.getInt("prompt_time", 2)+"\r\n");
			writer.write("ges_dist::0::"+share.getInt("ges_dist", 500)+"\r\n");
			writer.write("ges_speed::0::"+share.getInt("ges_speed", 200)+"\r\n");

			writer.close();
			handler.sendEmptyMessage(7);
		} catch (Exception e) {
			e.printStackTrace();
			handler.sendEmptyMessage(5);
		}
	}

	private void importSettings(final String path) {
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(path), "UTF-8"));
			String line = "";

			while (((line = reader.readLine()) != null)) {
				if (!line.contains("::")) continue;

				String[] ts = line.split("::");
				switch (Integer.parseInt(ts[1])) {
					case 1:
						if (2 == ts.length || "".equals(ts[2]))
						{
							edit.putBoolean(ts[0], false);
						}
						else {
							edit.putBoolean(ts[0], Boolean.parseBoolean(ts[2]));
						}
						break;

					case 2:
						if (2 == ts.length || "".equals(ts[2]))
						{
							edit.putString(ts[0], "");
						}
						else {
							edit.putString(ts[0], ts[2]);
						}
						break;

					default:if (2 == ts.length || "".equals(ts[2]))
					{
						edit.putInt(ts[0], 0);
					}
					else {
						edit.putInt(ts[0], Integer.parseInt(ts[2]));
					}
					break;
				}
			}

			reader.close();
			handler.sendEmptyMessage(12);
		} catch (Exception e) {
			e.printStackTrace();
			handler.sendEmptyMessage(11);
		}
	}

	private void outScr(final String path, final String fileName, final int num) {
		File fPath = new File(path);
		//Log.d("DCTimer", "==============" + path + "====" + fileName + "=======" + num);
		if(fPath.exists() || fPath.mkdirs()) {
			progressDialog.setTitle(getString(R.string.menu_outscr));
			progressDialog.setMax(num);
			progressDialog.show();
			new Thread() {
				public void run() {
					try {
						BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path+fileName), "utf-8"));
						for(int i=0; i<num; i++) {
							handler.sendEmptyMessage(100 + i);
							String s = (i+1) + ". " + scrambler.getScramble((scrIdx<<5)|scr2idx, false) + "\r\n";
							//Log.d("DCTimer", "==============" + s);
							writer.write(s);
						}
						writer.close();
						handler.sendEmptyMessage(7);
					} catch (IOException e) {
						handler.sendEmptyMessage(5);
					}
					progressDialog.dismiss();
				}
			}.start();
		}
		else Toast.makeText(context, getString(R.string.path_not_exist), Toast.LENGTH_SHORT).show();
	}
	
	private void outStat(String path, String fileName, String stat) {
		File fPath = new File(path);
		if(fPath.exists() || fPath.mkdir() || fPath.mkdirs()) {
			try {
				OutputStream out = new BufferedOutputStream(new FileOutputStream(path+fileName));
				byte [] bytes = stat.getBytes();
				out.write(bytes);
				out.close();
				Toast.makeText(context, getString(R.string.save_success), Toast.LENGTH_SHORT).show();
			} catch (IOException e) {
				Toast.makeText(context, getString(R.string.save_failed), Toast.LENGTH_SHORT).show();
			}
		}
		else Toast.makeText(context, getString(R.string.path_not_exist), Toast.LENGTH_SHORT).show();
	}
	
	private void download(final String fileName) {
		final File f = new File(defPath);
    	if(!f.exists()) f.mkdirs();
    	progressDialog.setTitle(getString(R.string.downloading));
    	progressDialog.setMax(100);
    	progressDialog.setProgress(0);
    	progressDialog.show();
        new Thread() {
        	public void run() {
        		try {
        			//Log.d("DCTimer", "===========https://github.com/andersgong/DCTimer2.0/raw/master/release/"+fileName);
                	URL url = new URL("https://github.com/andersgong/DCTimer2.0/raw/master/release/"+fileName);
                	URLConnection conn = url.openConnection();
                	conn.connect();
                	InputStream is = conn.getInputStream();
                	int filesum = conn.getContentLength();
					//Log.d("DCTimer", "===========filesum "+filesum);
                	if(filesum == 0) {
                		progressDialog.dismiss();
                		handler.sendEmptyMessage(6);
                		return;
                	}
                	progressDialog.setMax(filesum / 1024);
					//Log.d("DCTimer", "===========write "+defPath+fileName);
                	FileOutputStream fs = new FileOutputStream(defPath+fileName);
                	byte[] buffer = new byte[4096];
                	int byteread, bytesum = 0;
                	while ((byteread = is.read(buffer)) != -1) {
                		bytesum += byteread;
                		fs.write(buffer, 0, byteread);
                		handler.sendEmptyMessage(bytesum / 1024 + 100);
                	}
                	fs.close();
                	Intent intent = new Intent();
                	intent.setAction(android.content.Intent.ACTION_VIEW);
                	//intent.setDataAndType(Uri.parse("file://"+defPath+fileName), "application/vnd.android.package-archive");
                	intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
					if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
						//Log.d("DCTimer", "=================");
						intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
						Uri contentUri = FileProvider.getUriForFile(
								context
								, "com.dctimer.fileProvider"
								, new File(defPath+fileName));
						intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
					} else {
						intent.setDataAndType(Uri.parse("file://"+defPath+fileName), "application/vnd.android.package-archive");
					}
					startActivity(intent);
        		} catch (Exception e) {
        			//Log.d("DCTimer", "======" + e.getMessage());
        			handler.sendEmptyMessage(9);
        		}
        		progressDialog.dismiss();
        	}
        }.start();
	}
	
	private void getFileDirs(String path, boolean listFiles) {
		items = new ArrayList<String>();
		paths = new ArrayList<String>();
		File f = new File(path);
		File[] fs = f.listFiles();
		if(fs!=null && fs.length>0) Arrays.sort(fs, new Comparator<File>() {
			@Override
			public int compare(File arg0, File arg1) {
				String fn1 = arg0.getName();
				String fn2 = arg1.getName();
				return fn1.compareToIgnoreCase(fn2);
			}
		});
		if(!path.equals("/")) {
			items.add("..");
			paths.add(f.getParent());
		}
		if(fs != null) {
			for(int i=0; i<fs.length; i++) {
				File file = fs[i];
				if(file.isDirectory()) {
					items.add(file.getName());
					paths.add(file.getPath());
				}
			}
			if(listFiles) {
				for(int i=0; i<fs.length; i++) {
					File file = fs[i];
					if(!file.isDirectory()) {
						items.add(file.getName());
						paths.add(file.getPath());
					}
				}
			}
		}
		ArrayAdapter<String> fileList = new ArrayAdapter<String>(this, R.layout.list_item, items);
		listView.setAdapter(fileList);
	}
	
	public void showAlertDialog(int i, int j) {
		String t = null;
		switch(i) {
		case 1:
			t = String.format(stSel[14]==0 ? getString(R.string.sta_avg) : getString(R.string.sta_mean), l1len);
			slist = stSel[14]==0 ? averageOf(l1len, j) : meanOf(l1len, j);
			break;
		case 2:
			t = String.format(stSel[4]==0 ? getString(R.string.sta_avg) : getString(R.string.sta_mean), l2len);
			slist = stSel[4]==0 ? averageOf(l2len, j) : meanOf(l2len, j);
			break;
		case 3:
			t = getString(R.string.sta_session_mean);
			slist = sessionMean();
			break;
		}
		new CustomDialog.Builder(context).setTitle(t).setMessage(slist)
		.setPositiveButton(R.string.btn_copy, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialoginterface, int i) {
				if(VERSION.SDK_INT >= 11) {
					android.content.ClipboardManager clip = (android.content.ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
					clip.setPrimaryClip(ClipData.newPlainText("text", slist));
				}
				else {
					android.text.ClipboardManager clip = (android.text.ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
					clip.setText(slist);
				}
				Toast.makeText(context, getString(R.string.copy_to_clip), Toast.LENGTH_SHORT).show();
			}
		}).setNeutralButton(R.string.btn_save, new DialogInterface.OnClickListener() {
			LayoutInflater factory;
			EditText et1, et2;
			ImageButton btn;
			public void onClick(DialogInterface dialog, int which) {
				if(defPath == null) {
					Toast.makeText(context, getString(R.string.sd_not_exist), Toast.LENGTH_SHORT).show();
					return;
				}
				factory = LayoutInflater.from(context);
				int layoutId = R.layout.save_stat;
				view = factory.inflate(layoutId, null);
				et1 = (EditText) view.findViewById(R.id.edit_scrpath);
				btn = (ImageButton) view.findViewById(R.id.btn_browse);
				et1.setText(savePath);
				et2 = (EditText) view.findViewById(R.id.edit_scrfile);
				et2.requestFocus();
				et2.setText(String.format(getString(R.string.def_sname), formatter.format(new Date())));
				et2.setSelection(et2.getText().length());
				btn.setOnClickListener(new View.OnClickListener() {
					public void onClick(View v) {
						selFilePath = et1.getText().toString();
						int lid = R.layout.file_selector;
						final View view2 = factory.inflate(lid, null);
						listView = (ListView) view2.findViewById(R.id.list);
						File f = new File(selFilePath);
						selFilePath = f.exists() ? selFilePath : Environment.getExternalStorageDirectory().getPath()+File.separator;
						tvPathName = (TextView) view2.findViewById(R.id.text);
						tvPathName.setText(selFilePath);
						getFileDirs(selFilePath, false);
						listView.setOnItemClickListener(itemListener);
						new CustomDialog.Builder(context).setTitle(R.string.sel_path).setView(view2)
						.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialoginterface, int j) {
								et1.setText(selFilePath+"/");
							}
						}).setNegativeButton(R.string.btn_cancel, null).show();
					}
				});
				new CustomDialog.Builder(context).setView(view).setTitle(R.string.stat_save)
				.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface di, int i) {
						final String path=et1.getText().toString();
						if(!path.equals(savePath)) {
							savePath = path;
							edit.putString("scrpath", path);
							edit.commit();
						}
						final String fileName=et2.getText().toString();
						File file = new File(path+fileName);
						if(file.isDirectory()) Toast.makeText(context, getString(R.string.path_illegal), Toast.LENGTH_SHORT).show();
						else if(file.exists()) {
							new CustomDialog.Builder(context).setTitle(R.string.path_dupl)
							.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialoginterface, int j) {
									outStat(path, fileName, slist);
								}
							}).setNegativeButton(R.string.btn_cancel, null).show();
						} else outStat(path, fileName, slist);
						Utils.hideKeyboard(et1);
					}
				}).setNegativeButton(R.string.btn_cancel, new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface arg0, int arg1) {
						Utils.hideKeyboard(et1);
					}
				}).show();
			}
		}).setNegativeButton(R.string.btn_close, null).show();
	}
	
	private String getShareContent() {
		StringBuilder sb = new StringBuilder();
		sb.append(String.format(getString(R.string.share_c1), Session.length, btScramble.getText(),
				Statistics.timeAt(Statistics.minIdx, false), Statistics.timeToString(Statistics.mean)));
		if(Session.length>l1len) sb.append(String.format(getString(R.string.share_c2), l1len,
				Statistics.timeToString(Statistics.bestAvg[0])));
		if(Session.length>l2len) sb.append(String.format(getString(R.string.share_c2), l2len,
				Statistics.timeToString(Statistics.bestAvg[1])));
		sb.append(getString(R.string.share_c3));
		return sb.toString();
	}
	
	private void updateGridView(final int type) {
		new Thread() {
			public void run() {
				try {
					sleep(200);
				} catch (Exception e) { }
				switch (type) {
				case 1:
				case 3:
					handler.sendEmptyMessage(30);
					break;
				case 2:
					handler.sendEmptyMessage(31);
					break;
				}
				handler.sendEmptyMessage(17);
				if(type == 3) {
					handler.sendEmptyMessage(32);
				}
			}
		}.start();
	}
	
	private boolean update(int idx, int p) {
		if(Session.penalty[idx] != p) {
			session.update(idx, p);
			btSesMean.setText(getString(R.string.session_average) + Statistics.sessionMean());
			return true;
		}
		return false;
	}
	
	private void delete(int idx) {
		session.delete(idx, isMulp);
		btSesMean.setText(getString(R.string.session_average) + Statistics.sessionMean());
		updateGridView(1);
	}
	
	private void deleteAll() {
		session.clear();
		btSesMean.setText(getString(R.string.session_average) + "0/0): N/A (N/A)");
		Statistics.maxIdx = Statistics.minIdx = -1;
		updateGridView(1);
		if(sesType.get(sesIdx) != 32) {
			sesType.set(sesIdx, 32);
			edit.remove("sestype"+sesIdx);
			edit.commit();
		}
	}

	private void deleteSelectSes()
	{
		for (int i = delSesId.length - 1; i >= 1; i--) {
			if ( i == sesIdx )
				continue;
			if ( 0 != delSesId[i] ) {
				session.DelSession(i);
				DB_TBL_COUNT--;
				sesItems.remove(i);
				sesType.remove(i);
				sesnames.remove(i);
				sesAvgType1.remove(i);
				sesAvgNum1.remove(i);
				sesAvgType2.remove(i);
				sesAvgNum2.remove(i);

				if ( i < sesIdx )
				{
					sesIdx--;
				}
			}
		}

		edit.putInt("sescnt", DB_TBL_COUNT);

		for (int i = 0; i < sesnames.size(); i++) {
			sesItems.set(i, (i + 1) + ". " + sesnames.get(i));
			edit.putInt("sestype" + i, sesType.get(i));
			edit.putString("sesname" + i, sesnames.get(i));
			edit.putInt("sesavgtype1" + i, sesAvgType1.get(i));
			edit.putInt("sesavgnum1" + i, sesAvgNum1.get(i));
			edit.putInt("sesavgtype2" + i, sesAvgType2.get(i));
			edit.putInt("sesavgnum2" + i, sesAvgNum2.get(i));
		}

		scrIdx = sesType.get(sesIdx) >> 5;
		scr2idx = sesType.get(sesIdx) & 31;

		edit.putInt("sel", scrIdx);
		edit.putInt("group", sesIdx);
		edit.putInt("sel2", scr2idx);

		edit.commit();

		session.getSession(sesIdx, isMulp);
	}
	
	private String sessionMean() {
		StringBuffer sb = new StringBuffer();
		sb.append(getString(R.string.stat_title) + new java.sql.Date(new Date().getTime()) + "\r\n");
		sb.append(getString(R.string.stat_solve) + Statistics.solved + "/" + Session.length + "\r\n");
		sb.append(getString(R.string.ses_mean) + Statistics.timeToString(Statistics.mean) + " ");
		sb.append("(σ = " + Statistics.standardDeviation(Statistics.sd) + ")\r\n");
		sb.append(getString(R.string.ses_avg) + Statistics.sessionAvg() + "\r\n");
		if(Session.length >= l1len && Statistics.bestIdx[0] != -1) 
			sb.append(String.format(stSel[14]==0 ? getString(R.string.stat_best_avg) : getString(R.string.stat_best_mean), l1len)
					+ Statistics.timeToString(Statistics.bestAvg[0]) + "\r\n");
		if(Session.length >= l2len && Statistics.bestIdx[1] != -1) 
			sb.append(String.format(stSel[4]==0 ? getString(R.string.stat_best_avg) : getString(R.string.stat_best_mean), l2len)
					+ Statistics.timeToString(Statistics.bestAvg[1]) + "\r\n");
		sb.append(getString(R.string.stat_best) + Statistics.timeAt(Statistics.minIdx, false) + "\r\n");
		sb.append(getString(R.string.stat_worst) + Statistics.timeAt(Statistics.maxIdx, false) + "\r\n");
		sb.append(getString(R.string.stat_list));
		if(hidls) sb.append("\r\n");
		for(int i=0; i<Session.length; i++) {
			if(!hidls) sb.append("\r\n" + (i+1) + ". ");
			sb.append(Statistics.timeAt(i, true));
			String s = session.getString(i, 6);
			if(s!=null && !s.equals("")) sb.append("[" + s + "]");
			if(hidls && i<Session.length-1) sb.append(", ");
			if(!hidls) sb.append("  " + session.getString(i, 4));
		}
		return sb.toString();
	}

    private void currentMean() {
	    String mean5 = "N/A", mean12 = "N/A";
        int time;
/*
        if(Session.length >= l1len && Statistics.bestIdx[0] != -1)
            mean5 = Statistics.timeToString(Statistics.bestAvg[0]);
        if(Session.length >= l2len && Statistics.bestIdx[1] != -1)
            mean12 = Statistics.timeToString(Statistics.bestAvg[1]);
*/
        if(Session.length >= l1len)
        {
            mean5 = stSel[14] == 0 ? Statistics.average(l1len, Session.length - 1, 0) : Statistics.mean(l1len, Session.length - 1, 0);
        }
        if(Session.length >= l2len)
        {
            mean12 = stSel[4] == 0 ? Statistics.average(l2len, Session.length - 1, 1) : Statistics.mean(l2len, Session.length - 1, 1);
        }
        tvAvg.setText(String.format(getString(R.string.timer_mean), l1len, mean5, l2len, mean12, Statistics.timeAt(Statistics.minIdx, false), Statistics.sessionMean()));
    }

    private String averageOf(int n, int i) {
		ArrayList<Integer> midx = new ArrayList<Integer>();
		String[] avg = Statistics.getAvgDetail(n, i, midx);
		StringBuffer sb = new StringBuffer();
		sb.append(getString(R.string.stat_title) + new java.sql.Date(new Date().getTime()) + "\r\n");
		sb.append(getString(R.string.stat_avg) + avg[0] + " ");
		sb.append("(σ = " + avg[1] + ")\r\n");
		sb.append(getString(R.string.stat_best) + avg[2] + "\r\n");
		sb.append(getString(R.string.stat_worst) + avg[3] + "\r\n");
		sb.append(getString(R.string.stat_list));
		if(hidls) sb.append("\r\n");
		int num = 1;
		for(int j=i-n+1; j<=i; j++) {
			String s = session.getString(j, 6);
			if(!hidls) sb.append("\r\n" + (num++) + ". ");
			if(midx.indexOf(j) > -1) sb.append("(");
			sb.append(Statistics.timeAt(j, false));
			if(s!=null && !s.equals("")) sb.append("[" + s + "]");
			if(midx.indexOf(j) > -1) sb.append(")");
			if(hidls && j<i) sb.append(", ");
			if(!hidls) sb.append("  " + session.getString(j, 4));
		}
		return sb.toString();
	}
	
	private String meanOf(int n, int i) {
		String[] avg = Statistics.getMeanDetail(n, i);
		StringBuffer sb = new StringBuffer();
		sb.append(getString(R.string.stat_title) + new java.sql.Date(new Date().getTime()) + "\r\n");
		sb.append(getString(R.string.stat_mean) + avg[0] + " ");
		sb.append("(σ = " + avg[1] + ")\r\n");
		sb.append(getString(R.string.stat_best) + avg[2] + "\r\n");
		sb.append(getString(R.string.stat_worst) + avg[3] + "\r\n");
		sb.append(getString(R.string.stat_list));
		if(hidls) sb.append("\r\n");
		int num = 1;
		for(int j=i-n+1; j<=i; j++) {
			if(!hidls) sb.append("\r\n" + (num++) + ". ");
			sb.append(Statistics.timeAt(j, false));
			String s = session.getString(j, 6);
			if(s!=null && !s.equals("")) sb.append("[" + s + "]");
			if(hidls && j<i) sb.append(", ");
			if(!hidls) sb.append("  " + session.getString(j, 4));
		}
		return sb.toString();
	}
	
	private void acquireWakeLock() {
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
	}
	
	private void releaseWakeLock() {
		getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
	}
	
	public void showTime(final int p) {
		session.move(p);
		final String scr = session.getString(4);
		String time = session.getString(5);
		String n = session.getString(6);
		if(n==null) n="";
		final String comment = n;
		if(time!=null) time="\n("+time+")";
		else time = "";
		LayoutInflater factory = LayoutInflater.from(context);
		int layoutId = R.layout.singtime;
		view = factory.inflate(layoutId, null);
		editText = (EditText) view.findViewById(R.id.etnote);
		TextView tvTime = (TextView) view.findViewById(R.id.st_time);
		final TextView tvScr = (TextView) view.findViewById(R.id.st_scr);
		tvTime.setText(getString(R.string.show_time) + Statistics.timeAt(p, true) + time);
		tvScr.setText(scr);
		if(Session.penalty[p] == 2) {
			RadioButton rb = (RadioButton) view.findViewById(R.id.st_pe3);
			rb.setChecked(true);
		} else if(Session.penalty[p] == 1) {
			RadioButton rb = (RadioButton) view.findViewById(R.id.st_pe2);
			rb.setChecked(true);
		} else {
			RadioButton rb = (RadioButton) view.findViewById(R.id.st_pe1);
			rb.setChecked(true);
		}
		if(!comment.equals("")) {
			editText.setText(comment);
			editText.setSelection(comment.length());
		}
		new CustomDialog.Builder(context).setView(view)
		.setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				boolean tag = false;
				RadioGroup rg = (RadioGroup) view.findViewById(R.id.st_penalty);
				int rgid = rg.getCheckedRadioButtonId();
				switch(rgid) {
				case R.id.st_pe1: tag = update(p, 0); break;
				case R.id.st_pe2: tag = update(p, 1); break;
				case R.id.st_pe3: tag = update(p, 2); break;
				}
				String text = editText.getText().toString();
				if(!text.equals(comment)) {
					session.update(text);
					tag = true;
				}
				Utils.hideKeyboard(editText);
				if(tag) updateGridView(1);
			}
		}).setNeutralButton(R.string.copy_scr, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				if(VERSION.SDK_INT > 11) {
					android.content.ClipboardManager clip = (android.content.ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
					clip.setPrimaryClip(ClipData.newPlainText("text", scr));
				}
				else {
					android.text.ClipboardManager clip = (android.text.ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
					clip.setText(scr);
				}
				Toast.makeText(context, getString(R.string.copy_to_clip), Toast.LENGTH_SHORT).show();
				Utils.hideKeyboard(editText);
			}
		}).setNegativeButton(R.string.delete_time, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface d, int which) {
				delete(p);
				Utils.hideKeyboard(editText);
			}
		}).show();
	}
	
	private void setFullScreen(boolean fs) {
		if (fs)
			getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
		else getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
	}
	
	private void setSwitchOn(ImageButton bt, boolean isOn) {
		if(isOn) bt.setImageResource(R.drawable.switch_on);
		else bt.setImageResource(R.drawable.switch_off);
	}

    private void setRealMean(boolean isOn) {
        if(isOn) tvAvg.setVisibility(View.VISIBLE);
        else tvAvg.setVisibility(View.GONE);
    }
}
